2010-02-22 7 views
12

J'ai posé cette question plus tôt et il a été fermé parce que c'était un doublon, que j'accepte et que j'ai trouvé la réponse à la question Java: splitting a comma-separated string but ignoring commas in quotes, donc merci à quiconque a posté il.Séparer une chaîne sur des virgules ne figurant pas entre guillemets avec une torsion

Mais j'ai depuis rencontré un autre problème. Apparemment, ce que je dois faire est d'utiliser "," comme délimiteur quand il y a zéro ou un nombre pair de guillemets, mais aussi ignorer tout "," entre parenthèses.

Ainsi, les éléments suivants:

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

Est-ce que tokenizer comme:

  • Merci,
  • à l'avance,
  • pour ("le", "aide")

Je ne suis pas sûr s'il y a de toute façon de modifier la regex actuelle I J'utilise pour permettre cela, mais des conseils seraient appréciés.

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

Quel est le résultat souhaité? – DOK

+12

Vous devriez utiliser un vrai analyseur CSV pour gérer ce désordre. Le problème d'analyse ** non ** est mieux géré avec les regex. –

+1

@Joachim, Combien de parseurs CSV connaissez-vous qui peut gérer des guillemets, entre crochets, entre guillemets comme il le souhaite? –

Répondre

5

Parfois, il est plus facile de faire correspondre ce que vous voulez au lieu de ce que vous ne voulez pas:

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())); 
} 

Sortie:

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

Si vous avez besoin également d'ignorer les supports de fermeture à l'intérieur des sections de citations qui sont à l'intérieur des crochets, alors vous avez besoin de ceci:

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

Un exemple d'une chaîne qui a besoin de cette deuxième version est plus complexe:

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

Sortie:

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

Cependant, je vous conseille de changer le format de données si possible . Ce serait beaucoup plus facile si vous utilisiez un format standard comme XML pour stocker vos jetons.

3

Un développé localement est facilement écrit.

Par exemple, cette grammaire ANTLR prend soin de votre entrée exemple sans trop de difficulté:

parse 
    : line* 
    ; 

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

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

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

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

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

et il serait facile de l'étendre à prendre des citations ou échappées entre parenthèses en compte.

Lors de l'alimentation de l'analyseur généré par cette grammaire à suivre deux lignes d'entrée:

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

il s'analysables comme ceci:

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

Si vous envisagez d'utiliser ANTLR pour cela, Je peux poster un petit HOWTO pour obtenir un analyseur de cette grammaire que j'ai posté, si vous voulez.

Questions connexes