Это регулярное выражение неверно? Совпадений не найдено - PullRequest
2 голосов
/ 08 ноября 2011

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

Key1=value,Key2=value,Key3=value,Key4=value,Key5=value,Key6=value,Key7=value

Regex

((Key1)=(.*)),((Key2)=(.*)),((Key3)=(.*)),((Key4)=(.*)),((Key5)=(.*)),((Key6)=(.*)),((Key7)=(.*))

В самой строке количество ключей / значений примерно вдвое больше, но для краткости я оставляю его кратким.У меня они в скобках, поэтому я могу называть их группами.Ключи я сохранил как константы, и они всегда будут одинаковыми.Проблема в том, что он никогда не находит совпадения, которое не имеет смысла (если только регулярное выражение не верно)

Ответы [ 7 ]

8 голосов
/ 08 ноября 2011

Судя по вашему комментарию выше, похоже, что вы создаете объекты Pattern и Matcher и связываете Matcher с целевой строкой, но на самом деле вы не применяете регулярное выражение.Это очень распространенная ошибка.Вот полная последовательность:

String regex = "Key1=(.*),Key2=(.*)"; // etc.
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(targetString);
// Now you have to apply the regex:
if (m.find())
{
  String value1 = m.group(1);
  String value2 = m.group(2);
  // etc.
}

Мало того, что вы должны звонить find() или matches() (или lookingAt(), но никто никогда не использует это), вы всегда должны звонить в *Оператор 1009 * или while - то есть вы должны убедиться, что регулярное выражение действительно сработало , прежде чем вызывать какие-либо методы, такие как group(), требующие, чтобы Matcher находился в состоянии "соответствия".*

Также обратите внимание на отсутствие большинства ваших скобок.Они не были необходимы, и их исключение облегчает (1) чтение регулярных выражений и (2) отслеживание номеров групп.

2 голосов
/ 08 ноября 2011

Похоже, вам лучше поступить:

String[] pairs = data.split(",");

Затем анализируйте пары ключ / значение по одной

1 голос
/ 08 ноября 2011

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

"Key1=value1,Key2=value2"

вы добавите запятую так:

"Key1=value1,Key2=value2,"

Тогда регулярное выражение, которое дало мне самое близкое значение: "(?:(\\w+?)=(\\S+?),)?+" ... но это не совсем работает, если значения имеют запятые.

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

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

Теперь у вас будет набор подстрок, каждая из которых представляет собой набор символов, содержащих значениепоследняя запятая в строке, за которой следует ключ.Вы можете легко найти последнюю запятую в каждой подстроке, используя String.lastIndexOf(',').

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

1 голос
/ 08 ноября 2011

Ваше регулярное выражение работает на меня ...

Если вы всегда получаете IllegalStateException, я бы сказал, что вы пытаетесь сделать что-то вроде:

matcher.group(1);

без вызова метода find ().

Вам нужно вызвать этот метод перед любой попыткой получить группу (или вы будете в недопустимом состоянии для вызова метода group ())

Дайте попробовать:

    String test = "Key1=value,Key2=value,Key3=value,Key4=value,Key5=value,Key6=value,Key7=value";

    Pattern pattern = Pattern.compile("((Key1)=(.*)),((Key2)=(.*)),((Key3)=(.*)),((Key4)=(.*)),((Key5)=(.*)),((Key6)=(.*)),((Key7)=(.*))");

    Matcher matcher = pattern.matcher(test);

    matcher.find();

    System.out.println(matcher.group(1));
1 голос
/ 08 ноября 2011

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

((Key1)=(.*?)),((Key2)=(.*?)),((Key3)=(.*?)),((Key4)=(.*?)),((Key5)=(.*?)),((Key6)=(.*?)),((Key7)=(.*?))

Чтобы понять, почему оно требует такого большого количества возвратов, поймите, что для

Key1=(.*),Key2=(.*)

применяется к

Key1=x,Key2=y

Механизм регулярных выражений Java сопоставляет первые (.*) с x,Key2=y, а затем пытается убрать символы справа, пока не найдет совпадение для остальныхрегулярное выражение: ,Key2=(.*).В итоге он спрашивает:

  1. Соответствует ли "" 1017 *, нет, поэтому попробуйте
  2. Соответствует "y" ,Key2=(.*), нет, поэтому попробуйте
  3. Соответствует ли "=y" 1025 *, нет, попробуйте
  4. Соответствует "2=y" ,Key2=(.*), нет, попробуйте
  5. Соответствует "y2=y" ,Key2=(.*), нет, попробуйте
  6. Соответствует ли "ey2=y" 1037 *, нет, поэтому попробуйте
  7. Соответствует "Key2=y" ,Key2=(.*), нет, так что попробуйте
  8. Соответствует ",Key2=y" 10 * *, *да, поэтому первый .* - это "x", а второй - "y".

РЕДАКТИРОВАТЬ:

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

  1. Соответствует ли "x,Key2=(.*)" 1058 *, нет, так что попробуйте
  2. Соответствует ли ",Key2=(.*)" 1062 *, да.

Таким образом, когда у вас есть 7 ключей, не нужно сопоставлять 6 из них, что включает в себя несовпадение 5, которое включает в себя несовпадение 4, .... Это может сделать свою работу за один проход вперед повход.

0 голосов
/ 08 ноября 2011

Некоторые люди, столкнувшись с проблемой, думают: «Я знаю, я буду использовать регулярные выражения».Теперь у них две проблемы.- Джейми Завински

Самое простое решение - самое надежное.

final String data = "Key1=value,Key2=value,Key3=value,Key4=value,Key5=value,Key6=value,Key7=value";
final String[] pairs = data.split(",");
for (final String pair: pairs)
{
   final String[] keyValue = pair.split("=");
   final String key = keyValue[0];
   final String value = keyValue[1];
}
0 голосов
/ 08 ноября 2011

Если вы знаете, что у вас всегда есть 7, сопротивление взлома наименьшего составляет

^Key1=(.+),Key2=(.+),Key3=(.+),Key4=(.+),Key5=(.+),Key6=(.+),Key7=(.+)$

Попробуйте на http://www.fileformat.info/tool/regex.htm

Я почти уверен, что естьлучший способ проанализировать эту вещь, которая проходит через .find (), а не .matches (), который я думаю, я бы порекомендовал, так как он позволяет вам перемещаться вниз по строке одна пара ключ = значение за раз.Это переносит вас в целую «жадную» дискуссию по оценке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...