2010-02-22 24 views
12

Hice esta pregunta antes y se cerró porque era un duplicado, lo cual acepto y realmente encontré la respuesta en la pregunta Java: splitting a comma-separated string but ignoring commas in quotes, así que gracias a quien publicó eso.Dividir una cadena en comas que no figuran entre comillas dobles con un giro

Pero desde entonces me he encontrado con otro problema. Aparentemente, lo que tengo que hacer es usar "," como mi delimitador cuando hay cero o un número par de comillas dobles, pero también ignorar cualquier "," entre corchetes.

Así lo siguiente:

"Thanks,", "in advance,", "for("the", "help")" 

¿Sería tokenize como:

  • Gracias,
  • de antemano,
  • para ("el", "ayuda")

No estoy seguro de si hay alguna forma de modificar la expresión regular actual I Estoy usando para permitir esto, pero cualquier orientación sería apreciada.

line.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"); 
+0

¿Cuál es el resultado deseado? – DOK

+12

Debería utilizar un analizador CSV real para manejar ese lío. No ** cada ** problema de análisis se maneja mejor con expresiones regulares. –

+1

@Joachim, ¿Cuántos analizadores de CSV conoces que pueden manejar presupuestos, entre corchetes, dentro de comillas de la manera que él quiere? –

Respuesta

5

veces es más fácil para que coincida con lo que usted quiere en vez de lo que no quiere:

String s = "\"Thanks,\", \"in advance,\", \"for(\"the\", \"help\")\""; 
String regex = "\"(\\([^)]*\\)|[^\"])*\""; 
Pattern p = Pattern.compile(regex); 
Matcher m = p.matcher(s); 
while(m.find()) { 
    System.out.println(s.substring(m.start(),m.end())); 
} 

Salida:

"Thanks," 
"in advance," 
"for("the", "help")" 

Si también se tiene que ignorar el cierre de corchetes dentro de las secciones de cotizaciones que están dentro de los corchetes, entonces necesita esto:

String regex = "\"(\\((\"[^\"]*\"|[^)])*\\)|[^\"])*\""; 

Un ejemplo de una cadena que necesita esta segunda versión, más compleja es:

"foo","bar","baz(":-)",":-o")" 

Salida:

"foo" 
"bar" 
"baz(":-)",":-o")" 

Sin embargo, te aconsejo que para cambiar el formato de los datos, si es posible . Esto sería mucho más fácil si usa un formato estándar como XML para almacenar sus tokens.

3

A home-grown analizador es fácil de escribir.

Por ejemplo, esta gramática antlr se encarga de su ejemplo de entrada sin muchos problemas:

parse 
    : line* 
    ; 

line 
    : Quoted (',' Quoted)* ('\r'? '\n' | EOF) 
    ; 

Quoted 
    : '"' (Atom)* '"' 
    ; 

fragment 
Atom 
    : Parentheses 
    | ~('"' | '\r' | '\n' | '(' | ')') 
    ; 

fragment 
Parentheses 
    : '(' ~('(' | ')' | '\r' | '\n')* ')' 
    ; 

Space 
    : (' ' | '\t') {skip();} 
    ; 

y sería fácil de extender esto a tener citas o paréntesis escapado en cuenta.

Cuando se alimenta el analizador generado por que la gramática de las dos líneas de entrada:

"Thanks,", "in advance,", "for("the", "help")" 
"and(,some,more)","data , here" 

que se analiza como esta:

alt text http://i47.tinypic.com/258otvs.png

Si se tiene en cuenta para usar antlr para esto, Puedo publicar un poco de HOW-TO para obtener un analizador de esa gramática que publiqué, si lo desea.

Cuestiones relacionadas