Я пытаюсь извлечь пары ключ-значение из длинной строки в две основные формы: одну с одной и без кавычек, например
... a="First Field" b=SecondField ...
с использованием регулярного выражения Java
\b(a|b)\s*(?:=)\s*("[^"]*"|[^ ]*)\b
Однако, выполнив следующий тестовый код
public static void main(String[] args) {
String input = "a=\"First Field\" b=SecondField";
String regex = "\\b(a|b)\\s*(?:=)\\s*(\"[^\"]*\"|[^ ]*)\\b";
Matcher matcher = Pattern.compile(regex).matcher(input);
while (matcher.find()) {
System.out.println(matcher.group(1) + " = " + matcher.group(2));
}
}
выход
a = "First
b = SecondField
вместо желаемого (без кавычек)
a = First Field
b = SecondField
В более обобщенном виде, например
a ="First Field" b=SecondField c3= "Third field value" delta = "" e_value = five!
выход должен быть (опять же, без кавычек и с различным количеством пробелов до и после знака =
a = First Field
b = SecondField
c3 = Third field value
delta =
e_value = five!
Существует ли регулярное выражение для покрытия вышеупомянутого варианта использования (по крайней мере, версия с двумя ключами) или следует использовать обработку строк?
Еще более сложный вопрос: существует ли такое регулярное выражение, есть ли способ сохранить индекс группы сопряжений, соответствующий значению константы, так что и значение поля кавычек и значение без кавычек соответствуют одному и тому же групповому индексу?
Получить согласованную группу из индексов 1 и 2
(\w+)=(?:")?(.*?(?="?\s+\w+=|(?:"?)$))
здесь DEMO
образец кода:
String str = "a=\"First Field\" b=SecondField c=\"ThirdField\" d=\"FourthField\"";
Pattern p = Pattern.compile("(\\w+)=(?:\")?(.*?(?=\"?\\s+\\w+=|(?:\"?)$))");
Matcher m = p.matcher(str);
while (m.find()) {
System.out.println("key : " + m.group(1) + "\tValue : " + m.group(2));
}
вывод:
key : a Value : First Field
key : b Value : SecondField
key : c Value : ThirdField
key : d Value : FourthField
Если вы ищете только клавиши a
и b
просто сделайте небольшое изменение в шаблоне регулярных выражений.
Замените сначала \w+
a|b
(a|b)=(?:")?(.*?(?="?\s+\w+=|(?:"?)$))
Вот ДЕМО
Как отредактировать сообщение
просто добавьте \s
чтобы проверить также пробелы.
(\w+)\s*=\s*(?:")?(.*?(?="?\s+\w+\s*=|(?:"?)$))
Вы можете изменить свое регулярное выражение на следующее:
/\b(\w+)\s*=\s*(?:"([^"]*)"|([^ ]*)\b)/
Заметные изменения:
\w+
в java для записи символов слова [A-Za-z0-9_]
.=
в группу без захвата (?:=)
."
.См. Следующий код:
{
String input = "a =\"First Field\" b=SecondField c3= \"Third field value\" delta = \"\" e_value = five!";
String regex = "\\b(\\w+)\\s*=\\s*(?:\"([^\"]*)\"|([^ ]*)\\b)";
Matcher matcher = Pattern.compile(regex).matcher(input);
while (matcher.find())
System.out.println(matcher.group(1) + " = " +
(matcher.group(2) == null ? matcher.group(3) : matcher.group(2)));
}
Просмотрите демо-версию regex и демо-версию кода !
Демо-версия кода
STDOUT
:a = First Field b = SecondField c3 = Third field value delta = e_value = five
Ваше java regex "\ b (a | b)\s * (?: =)\S * (" [^ "]" | [^])\b "будет выдавать результат:
a = "First
b = SecondField
Это связано с тем, что после того, как "" "не является границей \b, поэтому ваша первая пара имя/значение с quotaiton никогда не будет сопоставлена.
Вы можете немного изменить это:
"\b(a|b)\s*=\s*(?:"([^"]*)"|([^ ]*))"
Весь образец кода указан ниже:
String input = "a=\"First Field\" b=SecondField";
String regex = "\\b(a|b)\\s*=\\s*(?:\"([^\"]*)\"|([^ ]*))";
Matcher matcher = Pattern.compile(regex).matcher(input);
while (matcher.find()) {
if(matcher.group(2) != null) {
System.out.println(matcher.group(1) + " = " + matcher.group(2));
}else {
System.out.println(matcher.group(1) + " = " + matcher.group(3));
}
}
Результат выглядит так:
a = First Field
b = SecondField
Между тем, если ваш ключ не просто "a или b", он работает, то вы можете изменить (a | b) на (\ w+)
(a|b)\s*(?:=)\s*("[^"]*"|[^ ]*)
Пробовал с этим. http://regex101.com/r/zR7cW9/1
a="First Field" b=SecondField c="ThirdField"
Second Field