Java регулярное выражение для извлечения полей с или без кавычек

1

Я пытаюсь извлечь пары ключ-значение из длинной строки в две основные формы: одну с одной и без кавычек, например

... 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!

Существует ли регулярное выражение для покрытия вышеупомянутого варианта использования (по крайней мере, версия с двумя ключами) или следует использовать обработку строк?

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

Теги:
string
key-value
quotes

4 ответа

3
Лучший ответ

Получить согласованную группу из индексов 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*=|(?:"?)$))

DEMO

  • 1
    @Unihedron, этот шаблон регулярных выражений также работает, если есть место для Second Field
8

Вы можете изменить свое регулярное выражение на следующее:

/\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
  • 2
    @Unihedron op хочет, чтобы второе поле было захвачено той же группой.
  • 0
    @AvinashRaj Условные и ветвления сброса не существует в Java. Как жаль , как это, мой простой подход (после user3218114 решения «ы ) будет использовать два захватив группу. Это возможно и в этом случае.
3

Ваше 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+)

0
    (a|b)\s*(?:=)\s*("[^"]*"|[^ ]*)

Пробовал с этим. http://regex101.com/r/zR7cW9/1

  • 0
    как насчет длинной строки для ex: a="First Field" b=SecondField c="ThirdField"
  • 0
    @ user3218114 ..... попытка re не была общей ... так что я тоже не пробовал .....

Ещё вопросы

Сообщество Overcoder
Наверх
Меню