2009-01-27 15 views
5

Mi cadena es el siguiente:¿Cómo puedo dividir esta cadena en una matriz?

smtp:[email protected];SMTP:[email protected];X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black; 

necesito volver:

smtp:[email protected] 
SMTP:[email protected] 
X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black; 

El problema es que los puntos y comas la separan las direcciones y también forma parte de la dirección X 400. ¿Alguien puede sugerir la mejor forma de dividir esto?

PD debe mencionado el orden es diferente por lo que podría ser:

X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;;smtp:[email protected];SMTP:[email protected] 

No puede haber más de 3 direcciones, 4, 5 .. 10 etc incluyendo una dirección X500, sin embargo, no todo el comienzo, ya sea con smtp: SMTP: X400 o X500.

+0

+1, una intrigante, ¡tanto que no he realizado ningún trabajo "real" durante los últimos 10 minutos! =) – Rob

Respuesta

9

EDITAR: Con la información actualizada, esta respuesta ciertamente no funcionará, pero aún es potencialmente útil, así que lo dejo aquí.

¿Siempre tendrá tres partes, y solo quiere dividir en los dos primeros punto y coma?

Si es así, sólo tiene que utilizar la sobrecarga de Split, que le permite especificar el número de subseries para volver:

string[] bits = text.Split(new char[]{';'}, 3); 
+0

+1 nunca supe sobre esta sobrecarga. ¡Parece que Java también lo tiene! –

+0

¡Puede haber más de 3 direcciones, 4, 5, 10, etc. incluyendo una dirección X500! –

+0

Todos comienzan con smtp: SMTP: X400 o X500 –

1

http://msdn.microsoft.com/en-us/library/c1bs0eda.aspx cheque allí, se puede especificar el número de divisiones que desee. por lo que en su caso se haría

string.split(new char[]{';'}, 3); 
+0

Según lo especificado, no sabe la cantidad de divisiones que se deben realizar. –

-1

Haz el punto y coma (;) y luego dividir un bucle sobre el resultado, volver a combinar cada elemento donde no hay dos puntos (:) con el elemento anterior.

string input = "X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=" 
    +"Black;;smtp:[email protected];SMTP:[email protected]"; 

string[] rawSplit = input.Split(';'); 

List<string> result = new List<string>(); 
    //now the fun begins 
string buffer = string.Empty; 
foreach (string s in rawSplit) 
{ 
    if (buffer == string.Empty) 
    { 
    buffer = s; 
    } 
    else if (s.Contains(':')) 
    { 
    result.Add(buffer); 
    buffer = s; 
    } 
    else 
    { 
    buffer += ";" + s; 
    } 
} 
result.Add(buffer); 

foreach (string s in result) 
    Console.WriteLine(s); 
+0

Parece que alguien bajó las respuestas correctas.Estoy votando cualquier respuesta que creo que es correcta (especialmente las respuestas que son downvoted sin explicación) y downvoting la pregunta (porque él sigue cambiando los requisitos). –

+0

'Cambiar los requisitos' es parte de lo que trata este sitio. Algunas veces el que pregunta no sabe exactamente qué o cómo se debe hacer la pregunta. Ver cómo llegan varias respuestas les ayuda a refinar la pregunta. –

+0

Claro, pero una cosa es cambiar la pregunta ... otra cosa que preguntar, obtener respuestas, cambiar y luego rechazar las respuestas correctas al original. –

1

Esto me llamó la curiosidad .... Así que este código en realidad hace el trabajo, pero una vez más, quiere poner en orden :)

Mi último intento - dejar de cambiar lo que necesita; =)

static void Main(string[] args) 
{ 
    string fneh = "X400:C=US400;A= ;P=Test;O=Exchange;S=Jack;G=Black;x400:C=US400l;A= l;P=Testl;O=Exchangel;S=Jackl;G=Blackl;smtp:[email protected];X500:C=US500;A= ;P=Test;O=Exchange;S=Jack;G=Black;SMTP:[email protected];"; 

    string[] parts = fneh.Split(new char[] { ';' }); 

    List<string> addresses = new List<string>(); 
    StringBuilder address = new StringBuilder(); 
    foreach (string part in parts) 
    { 
     if (part.Contains(":")) 
     { 
      if (address.Length > 0) 
      { 
       addresses.Add(semiColonCorrection(address.ToString())); 
      } 
      address = new StringBuilder(); 
      address.Append(part); 
     } 
     else 
     { 
      address.AppendFormat(";{0}", part); 
     } 
    } 
    addresses.Add(semiColonCorrection(address.ToString())); 

    foreach (string emailAddress in addresses) 
    { 
     Console.WriteLine(emailAddress); 
    } 
    Console.ReadKey(); 
} 
private static string semiColonCorrection(string address) 
{ 
    if ((address.StartsWith("x", StringComparison.InvariantCultureIgnoreCase)) && (!address.EndsWith(";"))) 
    { 
     return string.Format("{0};", address); 
    } 
    else 
    { 
     return address; 
    } 
} 
+0

Hola Rob, Esto casi funciona para mí, aparte del punto y coma se elimina de la dirección x400 que lo rompe (tengo que dejar los puntos y coma o anexar uno también) y acabo de descubrir que una dirección tiene dos x400 direcciones! X400 (mayúscula) indica una dirección primaria x400 (inferior) secundaria! Thks –

+0

Eso debería estar lo suficientemente cerca ... Siempre podría agregar un condicional a "semiColonCorrection" que solo agrega el ";" de vuelta al final para direcciones xNNN, no smtp ones .. – Rob

+0

Funcionó un encanto Rob, eres el HOMBRE! ¡Muchas gracias! –

0

Pruebe estas expresiones regulares. Puede extraer lo que está buscando utilizando grupos con nombre.

X400:(?<X400>.*?)(?:smtp|SMTP|$) 
smtp:(?<smtp>.*?)(?:;+|$) 
SMTP:(?<SMTP>.*?)(?:;+|$) 

Al hacer las construcciones, asegúrese de especificar mayúsculas y minúsculas. Parece que funcionan con las muestras que dio

+0

Está recogiendo las palabras smtp después de la dirección X400. –

+0

¿Está revisando los partidos o los grupos de partidos? – Rad

1

No es el más rápido si está haciendo esto mucho, pero funcionará para todos los casos, creo.

 string input1 = "smtp:[email protected];SMTP:[email protected];X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;"; 
     string input2 = "X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;;smtp:[email protected];SMTP:[email protected]"; 
     Regex splitEmailRegex = new Regex(@"(?<key>\w+?):(?<value>.*?)(\w+:|$)"); 

     List<string> sets = new List<string>(); 

     while (input2.Length > 0) 
     { 
      Match m1 = splitEmailRegex.Matches(input2)[0]; 
      string s1 = m1.Groups["key"].Value + ":" + m1.Groups["value"].Value; 
      sets.Add(s1); 
      input2 = input2.Substring(s1.Length); 
     } 

     foreach (var set in sets) 
     { 
      Console.WriteLine(set); 
     } 

     Console.ReadLine(); 

Por supuesto, muchos reclamarán Regex: Ahora tiene dos problemas. Incluso puede haber una mejor respuesta de expresiones regulares que esta.

1

Siempre podría dividirse en los dos puntos y tener un poco de lógica para tomar la tecla y el valor.

string[] bits = text.Split(':'); 
List<string> values = new List<string>(); 
for (int i = 1; i < bits.Length; i++) 
{ 
    string value = bits[i].Contains(';') ? bits[i].Substring(0, bits[i].LastIndexOf(';') + 1) : bits[i]; 
    string key = bits[i - 1].Contains(';') ? bits[i - 1].Substring(bits[i - 1].LastIndexOf(';') + 1) : bits[i - 1]; 
    values.Add(String.Concat(key, ":", value)); 
} 

Lo probé con sus dos muestras y funciona bien.

4

puedo sugerir la construcción de una expresión regular

(smtp|SMTP|X400|X500):((?!smtp:|SMTP:|X400:|X500:).)*;? 

o protocolo de menos

.*?:((?![^:;]*:).)*;? 

en otras palabras, encontrar cualquier cosa que comienza con uno de sus protocolos. Haga coincidir los dos puntos Luego continúe haciendo coincidir caracteres siempre que no coincida con uno de sus protocolos. Termine con un punto y coma (opcionalmente).

Luego puede analizar la lista de coincidencias divididas en ':' y tendrá sus protocolos. Además, si desea agregar protocolos, simplemente agréguelos a la lista.

Sin embargo, es probable que desee especificar todo el asunto como "no distinguir mayúsculas y minúsculas" y solo enumerar los protocolos en sus versiones en mayúsculas o minúsculas.

La versión sin protocolo no importa cuáles son los nombres de los protocolos. Simplemente los encuentra todos iguales, haciendo coincidir todo hasta, pero excluyendo una cadena seguida de dos puntos o un punto y coma.

+0

Esto casi funciona pero existe la suposición de que las direcciones no contienen el texto smtp, X400 o X500. – AnthonyWJones

+0

Los formatos de cadena simples realmente, realmente no necesitan expresiones regulares para dividirlos en mi humilde opinión, pero este es un caso decente para una expresión regular. –

+0

Estoy de acuerdo en que no debe usar Regex donde string.Split funcionará (y es por eso que el procesamiento de dos puntos está hecho en string.Split), pero tan pronto como termine escribiendo un trozo de código para el procesamiento de cadenas, creo que debería comenzar para ver regex por hacer lo mismo (son mejores en eso). –

3

dividida por el siguiente patrón de expresión

string[] items = System.Text.RegularExpressions.Split(text, ";(?=\w+:)"); 

EDIT: uno mejor puede aceptar caracteres especiales en el nombre del protocolo.

string[] items = System.Text.RegularExpressions.Split(text, ";(?=[^;:]+:)"); 
+0

No funciona para las expresiones involucradas si hay un espacio después del punto y coma. –

+0

Lo he probado en http://www.regextester.com/ y funciona (puede identificar el ";" correcto en la cadena). ¿Podría ser el problema de compatibilidad de bandera o preg? –

+0

Intente agregar un espacio después del punto y coma, pero antes del siguiente protocolo y no coincidirá con ese punto y coma. –

-1

aquí hay otra posible solución.

string[] bits = text.Replace(";smtp", "|smtp").Replace(";SMTP", "|SMTP").Replace(";X400", "|X400").Split(new char[] { '|' });

bits de [0], bits de [1], y bits de [2] entonces contiene las tres partes en el orden de su cadena original.

+0

Obviamente, el ejemplo tal como está no coincidirá con 'smtp' al principio. Creo que todas las sustituciones deben estar sin el punto y coma, p. texto. Reemplazar ("smtp", "| smtp"). La ordenación final en el resultado puede tener un TrimEnd (';') y la división se puede hacer con RemoveEmptyEntries para deshacerse del primer – Carl

+0

en blanco. Mi solución también intenta atender a la otra cadena de entrada, que es 'X400: C = US; A =; P = Prueba; O = Intercambio; S = Jack; G = Negro ;; smtp: [email protected]; SMTP: jb @ test.com' – mangokun

+0

Así será mi alteración, depende de cómo importante son los puntos y coma, ya que los tuyos los están eliminando. – Carl

0

Muchos intentos. Aquí es mío)

string src = "smtp:[email protected];SMTP:[email protected];X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;"; 

Regex r = new Regex(@" 
    (?:^|;)smtp:(?<smtp>([^;]*(?=;|$)))| 
    (?:^|;)x400:(?<X400>.*?)(?=;x400|;x500|;smtp|$)| 
    (?:^|;)x500:(?<X500>.*?)(?=;x400|;x500|;smtp|$)", 
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); 

foreach (Match m in r.Matches(src)) 
{ 
    if (m.Groups["smtp"].Captures.Count != 0) 
     Console.WriteLine("smtp: {0}", m.Groups["smtp"]); 
    else if (m.Groups["X400"].Captures.Count != 0) 
     Console.WriteLine("X400: {0}", m.Groups["X400"]); 
    else if (m.Groups["X500"].Captures.Count != 0) 
     Console.WriteLine("X500: {0}", m.Groups["X500"]); 
} 

Esto encuentra todas las direcciones SMTP, x400 o x500 en la cadena en cualquier orden de aparición. También identifica el tipo de dirección lista para un procesamiento posterior. La apariencia del texto smtp, x400 o x500 en las direcciones mismas no alterará el patrón.

0

Esto funciona!

string input = 
     "smtp:[email protected];SMTP:[email protected];X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;"; 
    string[] parts = input.Split(';'); 
    List<string> output = new List<string>(); 
    foreach(string part in parts) 
    { 
     if (part.Contains(":")) 
     { 
      output.Add(part + ";"); 
     } 
     else if (part.Length > 0) 
     { 
      output[output.Count - 1] += part + ";"; 
     } 
    } 
    foreach(string s in output) 
    { 
     Console.WriteLine(s); 
    } 
Cuestiones relacionadas