Escape запятая при использовании String.split

Я пытаюсь выполнить некоторые простые простые обработки файлов журнала, поэтому я использую метод String.split следующим образом:

String [] parts = input.split(",");

И отлично работает для ввода, например:

a,b,c

или

type=simple, output=Hello, repeat=true 

Просто сказать что-то.

Как я могу избежать запятой, поэтому она не соответствует промежуточным запятым?

Например, если я хочу включить запятую в одну из частей:

type=simple, output=Hello, world, repeate=true

Я думал в чем-то вроде:

type=simple, output=Hello\, world, repeate=true

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

Я пробовал:

String [] parts = input.split("[^\,],");

Но, ну, не работает.

Ответы

Ответ 1

Вы можете решить эту проблему, используя негативный внешний вид.

String[] parts = str.split("(?<!\\\\), ");

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

String str = "type=simple, output=Hello\\, world, repeate=true";
String[] parts = str.split("(?<!\\\\), ");
for (String s : parts)
    System.out.println(s);

Вывод:

type=simple
output=Hello\, world
repeate=true

(ссылка ideone.com)


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

String[] parts = str.split(", (?=\\w+=)");

Который говорит, что раскол на каждом ", ", за которым следуют некоторые слова-символы и an =

(ссылка ideone.com)

Ответ 2

Боюсь, нет идеального решения для String.split. Использование счетчика для трех частей будет работать. Если количество деталей не является постоянным, я бы рекомендовал цикл с matcher.find. Что-то вроде этого возможно

final String s = "type=simple, output=Hello, world, repeat=true";
final Pattern p = Pattern.compile("((?:[^\\\\,]|\\\\.)*)(?:,|$)");
final Matcher m = p.matcher(s);
while (m.find()) System.out.println(m.group(1));

Вы, вероятно, захотите пропустить пробелы и после запятой:

final Pattern p = Pattern.compile("((?:[^\\\\,]|\\\\.)*)(?:,\\s*|$)");

Это не очень сложно, просто отметьте, что вам нужно четыре обратной косой черты, чтобы соответствовать одному.

Ответ 3

Escaping работает с противоположностью ответа aioobe (обновлено: aioobe теперь использует ту же конструкцию, но я не знал, что когда я это написал), negative lookbehind

final String s = "type=simple, output=Hello\\, world, repeate=true";
final String[] tokens = s.split("(?<!\\\\),\\s*");
for(final String item : tokens){
    System.out.println("'" + item.replace("\\,", ",") + "'");
}

Вывод:

'тип = простой'
'output = Hello, world'
'Repeate = истина'

Справка:

Ответ 4

Я думаю,

input.split("[^\\\\],");

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