2008-09-26 27 views
21

Tengo una secuencia de datos que puede contener \ r, \ n, \ r \ n, \ n \ r o cualquier combinación de ellas. ¿Existe una forma simple de normalizar los datos para hacer que todos ellos simplemente se conviertan en \ r \ n pares para hacer que la visualización sea más consistente?Normalizar nuevas líneas en C#

Así que algo que produciría este tipo de tabla de traducción:

\r  --> \r\n 
\n  --> \r\n 
\n\n --> \r\n\r\n 
\n\r --> \r\n 
\r\n --> \r\n 
\r\n\n --> \r\n\r\n 
+2

Espera, ¿quieres que \ n \ r se correlacione con \ r \ n? Eso no es normalización. Ninguna plataforma común usa \ n \ r como un final de línea. –

+2

No lo dije como una plataforma normal, ¿verdad? He visto código de datos (del código VB específicamente) que lo tiene de esa manera, y tengo que dar cuenta de ello. Perdón si eso no cumple con la definición estricta de "normalizar", pero sin duda cumple con la definición de los datos que necesito procesar, que es el punto – ctacke

Respuesta

29

creo que esto va a hacer lo que necesita:

using System.Text.RegularExpressions; 
// ... 
string normalized = Regex.Replace(originalString, @"\r\n|\n\r|\n|\r", "\r\n"); 

no estoy 100% seguro de la sintaxis exacta, y no tengo un compilador .Net práctico para comprobar. Lo escribí en perl, y lo convertí en (con suerte correcto) C#. El único truco real es hacer coincidir "\ r \ n" y "\ n \ r" primero.

Para aplicarlo a una secuencia completa, simplemente ejecute en trozos de entrada. (Se puede hacer esto con una envoltura de secuencia si lo desea.)


El Perl originales:

$str =~ s/\r\n|\n\r|\n|\r/\r\n/g; 

Los resultados de las pruebas:

[bash$] ./test.pl 
\r -> \r\n 
\n -> \r\n 
\n\n -> \r\n\r\n 
\n\r -> \r\n 
\r\n -> \r\n 
\r\n\n -> \r\n\r\n 

Actualización: ahora convierte \ n \ r to \ r \ n, aunque no llamaría a eso normalización.

+0

Esto no cumplía con los requisitos del ejemplo anterior en la tabla. Mire la expresión regular que modifiqué, debe dar cuenta de \ n \ n. –

+0

Éste está cerca, pero \ n \ r debería simplemente intercambiar los elementos para que sean \ r \ n (vi esta entrada desde el código de un desarrollador de VB) – ctacke

+0

Ok, hice ese cambio. No consideraría esa normalización, pero es bastante fácil de agregar a la expresión regular. –

3

una expresión regular ayudaría .. podría hacer algo más o menos así ..

(\ r \ n | \ n \ n | \ n \ r | \ r | \ n) reemplazar con \ r \ n

Esta expresión regular produjo estos resultados de la tabla publicada (solo prueba del lado izquierdo) por lo que una sustitución debería normalizarse.

\r => \r 
\n => \n 
\n\n => \n\n 
\n\r => \n\r 
\r\n => \r\n 
\r\n => \r\n 
\n => \n 
+0

Excepto si ya contiene \ r \ n, el reemplazo expandiría eso a \ r \ n \ r \ n. Lo mismo para \ n \ r. Creo que la respuesta está en el arcano lenguaje de la expresión regular, pero para mí es un arte negro. – ctacke

+0

CQ, eso no hace lo que pidió. Una expresión regular podría funcionar, pero no como la has publicado. –

+0

Estoy de acuerdo en que no he tenido en cuenta \ r \ n –

0

Estás pensando demasiado complicado. Ignora cada \ r y convierte cada \ n en un \ r \ n.

En Pseudo-C#:

char[] chunk = new char[X]; 
StringBuffer output = new StringBuffer(); 

buffer.Read(chunk); 
foreach (char c in chunk) 
{ 
    switch (c) 
    { 
     case '\r' : break; // ignore 
     case '\n' : output.Append("\r\n"); 
     default : output.Append(c); 
    } 
} 

EDITAR: solo \ r hay una línea terminador lo que duda de que realmente desea ampliar \ r \ r \ n.

+0

Él quiere que \ r \ n \ r \ n \ r \ n \ r \ ntheree \ r \ r \ nse vuelva \ r \ n también. –

+0

Hm. No puedo creer que realmente lo quiera :) – VVS

+4

Macs usó CR para linebreaks hasta MacOS 9. Es \ n \ r que me sorprende. –

3

estoy con Jamie Zawinski en RegEx:

"Algunas personas, cuando se enfrentan a un problema, piensan" Yo sé, voy a usar expresiones regulares."Ahora tienen dos problemas"

Para aquellos de nosotros que prefieren la legibilidad:

  • Paso 1

    Reemplazar \ r \ n de \ n

    Reemplazar \ n \ r por \ n (si realmente quieres esto, algunos carteles no parecen pensar)

    Reemplazar \ r por \ n

  • Paso 2 Sustituir \ n por Environment.NewLine o \ r \ n o lo que sea.

+5

Esta es una expresión regular trivial. Estoy de acuerdo con usted si fuera un análisis de HTML. – cchamberlain

1

Acepto que Regex es la respuesta, sin embargo, todos los demás no mencionan los separadores de línea Unicode. Esos (y sus variaciones con \ n) deberían incluirse.

+1

¿Tiene una solución para eso? Sería útil saber – Phil

0

normalizar las roturas, por lo que todos ellos son \r\n

var normalisedString = 
      sourceString 
      .Replace("\r\n", "\n") 
      .Replace("\n\r", "\n") 
      .Replace("\r", "\n") 
      .Replace("\n", "\r\n"); 
0

Esta es la respuesta a la pregunta. La solución dada reemplaza una cadena por la tabla de traducción dada. No usa una función de expresión regular costosa. Tampoco utiliza funciones de reemplazo múltiples que cada uno individualmente recorrió los datos con varias comprobaciones, etc.

Por lo tanto, la búsqueda se realiza directamente en 1 para el ciclo. Para el número de veces que se debe aumentar la capacidad de la matriz de resultados, también se utiliza un bucle dentro de la función Array.Copy. Eso son todos los bucles. En algunos casos, un tamaño de página mayor puede ser más eficiente.

public static string NormalizeNewLine(this string val) 
{ 
    if (string.IsNullOrWhiteSpace(val)) 
     return val; 

    const int page = 6; 
    int a = page; 
    int j = 0; 
    int len = val.Length; 
    char[] res = new char[len]; 

    for (int i = 0; i < len; i++) 
    { 
     char ch = val[i]; 

     if (ch == '\r') 
     { 
      int ni = i + 1; 
      if (ni < len && val[ni] == '\n') 
      { 
       res[j++] = '\r'; 
       res[j++] = '\n'; 
       i++; 
      } 
      else 
      { 
       if (a == page) //ensure capacity 
       { 
        char[] nres = new char[res.Length + page]; 
        Array.Copy(res, 0, nres, 0, res.Length); 
        res = nres; 
        a = 0; 
       } 

       res[j++] = '\r'; 
       res[j++] = '\n'; 
       a++; 
      } 
     } 
     else if (ch == '\n') 
     { 
      int ni = i + 1; 
      if (ni < len && val[ni] == '\r') 
      { 
       res[j++] = '\r'; 
       res[j++] = '\n'; 
       i++; 
      } 
      else 
      { 
       if (a == page) //ensure capacity 
       { 
        char[] nres = new char[res.Length + page]; 
        Array.Copy(res, 0, nres, 0, res.Length); 
        res = nres; 
        a = 0; 
       } 

       res[j++] = '\r'; 
       res[j++] = '\n'; 
       a++; 
      } 
     } 
     else 
     { 
      res[j++] = ch; 
     } 
    } 

    return new string(res, 0, j); 
} 

La tabla de traducción realmente me atrae aunque '\ n' no se use realmente en las plataformas básicas. ¿Quién usaría dos tipos de saltos de línea en sucesión para indicar 2 saltos de línea? Si quiere saber eso, entonces debe echar un vistazo antes para saber si \ ny \ r Ambos se usan por separado en el mismo documento.

Cuestiones relacionadas