Разбить строку на запятые, не содержащиеся в двойных кавычках с изюминкой - PullRequest
12 голосов
/ 22 февраля 2010

Я задавал этот вопрос ранее, и он был закрыт, потому что это был дубликат, который я принял и фактически нашел ответ в вопросе Java: разбиение строки через запятую, но игнорирование запятых в кавычках , поэтому спасибо тому, кто это опубликовал.

Но с тех пор я столкнулся с другой проблемой. Очевидно, что мне нужно использовать "," в качестве разделителя, когда есть нулевое или четное число двойных кавычек, но также игнорировать любые ",", заключенные в скобки.

Итак, следующее:

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

Будет маркироваться как:

  • Спасибо
  • заранее,
  • для ("the", "help")

Я не уверен, есть ли возможность изменить текущее регулярное выражение, которое я использую, чтобы учесть это, но любые рекомендации будут оценены.

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

Ответы [ 2 ]

5 голосов
/ 22 февраля 2010

Иногда проще сопоставить то, что вы хотите, а не то, что вы не хотите:

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

Выход:

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

Если вам также нужно игнорировать закрывающие скобки внутри разделов кавычек, которые находятся внутри скобок, то вам нужно это:

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

Пример строки, которая нуждается во второй, более сложной версии:

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

Выход:

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

Однако я бы посоветовал вам изменить формат данных, если это возможно. Это было бы намного проще, если бы вы использовали стандартный формат, такой как XML, для хранения своих токенов.

3 голосов
/ 22 февраля 2010

A доморощенный парсер легко пишется.

Например, эта грамматика ANTLR позаботится о вашем вводном примере без особых проблем:

parse
  :  line*
  ;

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

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

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

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

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

и было бы легко расширить это, чтобы учесть экранированные кавычки или круглые скобки.

При подаче синтаксического анализатора, сгенерированного этой грамматикой, на следующие две строки ввода:

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

это анализируется так:

alt text

Если вы решите использовать ANTLR для этого, я могу опубликовать небольшое руководство, чтобы получить парсер из той грамматики, которую я разместил, если хотите.

...