2010-07-16 17 views
6

No soy bueno en expresiones regulares. ¿Puede alguien ayudarme a escribir expresiones regulares para mí?regex para dividir línea (archivo csv)

Es posible que tenga valores como este al leer el archivo csv.

 
"Artist,Name",Album,12-SCS 
"val""u,e1",value2,value3 

Salida:

 
Artist,Name 
Album 
12-SCS 
Val"u,e1 
Value2 
Value3 

Actualización: me gusta la idea usando proveedor OLEDB. Tenemos el control de carga de archivos en la página web, que leo el contenido del archivo usando el lector de flujo sin guardar el archivo en el sistema de archivos. ¿Hay alguna forma de que pueda usar el proveedor Oledb porque necesitamos especificar el nombre del archivo en la cadena de conexión y en mi caso no tengo el archivo guardado en el sistema de archivos?

+0

esto va a ser complicado, con una expresión regular , ¿ha considerado analizar usando una máquina de estados finitos? – stimms

+0

http://regex.info/blog/2006-09-15/247 –

Respuesta

0

Regex puede ser demasiado complejo aquí. Dividir la línea en comas, y luego iterar sobre los bits resultantes y concatenarlos donde "el número de comillas dobles en la cadena concatenada" no es par.

"Hola, este", es "un "" prueba" ""

... ... dividida

"hola | este" | es | "A '' prueba" ""

... iteración y combinar 'hasta que haya un número par de comillas dobles ...

'Hola, este' - un número par de frases (nota coma retira por división insertada entre bits)

es - un número par de frases

"a '' prueba" "" - un número par de frases

... entonces tira de ataque y de salida cotización si está presente y reemplace "" por ".

6

Regex no es la herramienta adecuada para esto. Use un analizador CSV . O bien el builtin uno o el 3rd party uno.

+0

De acuerdo, la expresión regular es la herramienta incorrecta. Utilicé el CsvReader al que se vinculó en CodeProject y me pareció excelente para manejar archivos csv. –

+0

Me gusta la idea con el proveedor de Oledb. Tenemos el control de carga de archivos en la página web, que leo el contenido del archivo usando el lector de flujo sin guardar el archivo en el sistema de archivos. ¿Hay alguna forma de que pueda usar el proveedor Oledb porque necesitamos especificar el nombre del archivo en la cadena de conexión y en mi caso no tengo el archivo guardado en el sistema de archivos? – shailesh

+0

Esa es una nueva pregunta. Intenta hacer una pregunta ** nueva ** con el título, el contexto y las etiquetas correctos. – BalusC

5

Dale un vistazo a la clase TextFieldParser. Está en el ensamblado Microsoft.VisualBasic y realiza un análisis delimitado y de ancho fijo.

+0

+1 para TextFieldParser. Es una de las gemas ocultas de .NET - Posiblemente porque está escondida en el espacio de nombres de Visual Basic por alguna razón. (P.S. * Siempre * siga el consejo de Brian S. ¡Esos tipos son realmente inteligentes!) –

1

Prueba CsvHelper (una biblioteca que mantengo). Está disponible a través de NuGet.

Puede leer fácilmente un archivo CSV en una colección de clases personalizada. También es muy rápido.

var streamReader = // Create a StreamReader to your CSV file 
var csvReader = new CsvReader(streamReader); 
var myObjects = csvReader.GetRecords<MyObject>(); 
8

En realidad, es bastante fácil hacer coincidir las líneas CVS con una expresión regular. Prueba con esto a cabo:

StringCollection resultList = new StringCollection(); 
try { 
    Regex pattern = new Regex(@" 
     # Parse CVS line. Capture next value in named group: 'val' 
     \s*      # Ignore leading whitespace. 
     (?:      # Group of value alternatives. 
      ""      # Either a double quoted string, 
      (?<val>    # Capture contents between quotes. 
      [^""]*(""""[^""]*)* # Zero or more non-quotes, allowing 
     )      # doubled "" quotes within string. 
      ""\s*     # Ignore whitespace following quote. 
     | (?<val>[^,]*)   # Or... zero or more non-commas. 
     )      # End value alternatives group. 
     (?:,|$)     # Match end is comma or EOS", 
     RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace); 
    Match matchResult = pattern.Match(subjectString); 
    while (matchResult.Success) { 
     resultList.Add(matchResult.Groups["val"].Value); 
     matchResult = matchResult.NextMatch(); 
    } 
} catch (ArgumentException ex) { 
    // Syntax error in the regular expression 
} 

exención de responsabilidad: La expresión regular ha sido probado en RegexBuddy, (que generó este fragmento), y correctamente coincide con los datos de prueba OP, pero la lógica del código de C no se ha probado. (No tengo acceso a las herramientas de C#)

+0

@viggity - Me alegra ayudar. También es posible que desee echar un vistazo a una solución de expresiones regulares más complicada para analizar líneas CSV. Consulte: [¿Cómo puedo analizar una cadena CSV con Javascript?] (Http://stackoverflow.com/a/8497474/433790) – ridgerunner

11

Solo agregué la solución en la que trabajé esta mañana.

var regex = new Regex("(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)"); 

foreach (Match m in regex.Matches("<-- input line -->")) 
{ 
    var s = m.Value; 
} 

Como se puede ver, tiene que llamar regex.Matches() por línea. Luego devolverá una MatchCollection con el mismo número de elementos que tiene como columnas. La propiedad Value de cada coincidencia es, obviamente, el valor analizado.

Este es todavía un trabajo en progreso, pero felizmente análisis sintáctico de cadenas CSV como:

2,3.03,"Hello, my name is ""Joshua""",A,B,C,,,D 
0

Se podría hacer mediante el siguiente código:

using Microsoft.VisualBasic.FileIO; 
string csv = "1,2,3,"4,3","a,"b",c",end"; 
TextFieldParser parser = new TextFieldParser(new StringReader(csv)); 
//To read from file 
//TextFieldParser parser = new TextFieldParser("csvfile.csv"); 
parser.HasFieldsEnclosedInQuotes = true; 
parser.SetDelimiters(","); 
string[] fields =null; 
while (!parser.EndOfData) 
{ 
    fields = parser.ReadFields(); 
} 
parser.Close(); 
Cuestiones relacionadas