Невозможно сопоставить строку с помощью регулярного выражения - PullRequest
7 голосов
/ 07 октября 2010

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

"(?<=(.*?id(( *)=)\\s[\"\']))g"

не соответствует строке

<input id = "g" />

в Java?

Ответы [ 4 ]

6 голосов
/ 07 октября 2010

Java.util.regex не поддерживает бесконечный просмотр, как описано в RegexBuddy :

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

Чтобы добавить небольшое пояснение из документации:

Поэтому многие разновидности регулярных выражений, в том числе используемые в Perl и Python, допускают только строки фиксированной длины.Вы можете использовать любое регулярное выражение, длина которого может быть заранее определена.Это означает, что вы можете использовать буквенный текст и классы символов.Вы не можете использовать повторение или дополнительные элементы.Вы можете использовать чередование, но только если все параметры чередования имеют одинаковую длину.

Некоторые разновидности регулярных выражений, такие как PCRE и Java, поддерживают вышеупомянутое, плюс чередование со строками разной длины.Каждая часть чередования должна иметь конечную максимальную длину.Это означает, что вы по-прежнему не можете использовать звезду или плюс, но вы можете использовать знак вопроса и фигурные скобки с указанным параметром max.Эти регулярные выражения признают тот факт, что конечное повторение может быть переписано как чередование строк с различной, но фиксированной длиной.К сожалению, в JDK 1.4 и 1.5 есть некоторые ошибки, когда вы используете чередование внутри lookhhind.Они были исправлены в JDK 1.6.

2 голосов
/ 07 октября 2010

Java не только не допускает неограниченного просмотра, но и при попытке выдает исключение. Тот факт, что вы не видите это исключение, сам по себе ошибка .

Вы все равно не должны использовать lookbehind для этого. Если вы хотите сопоставить значение определенного атрибута, самый простой и наименее хлопотный подход - сопоставить весь атрибут и использовать группу захвата для извлечения значения. Например:

String source = "<input id = \"g\" />"; 
Pattern p = Pattern.compile("\\bid\\s*=\\s*\"([^\"]*)\"");
Matcher m = p.matcher(source);
if (m.find())
{
  System.out.printf("Found 'id' attribute '%s' at position %d%n",
                    m.group(1), m.start());
}

Выход:

Found 'id' attribute 'g' at position 7

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

2 голосов
/ 07 октября 2010

Итак, несколько человек объяснили, почему ваше регулярное выражение не работает (и это действительно фатально; регулярные выражения Java не могут делать то, что вам нужно).Тем не менее, вам может быть интересно, как вы должны теперь анализировать это ...

Похоже, что строка, которую вы пытаетесь проанализировать, является XML.Regex действительно не очень хороший подход к анализу XML;существует несоответствие между тем, что может быть закодировано в XML, и тем, что можно сопоставить с помощью регулярных выражений.Так что, если это часть некоторого текста XML, возможно, стоит подумать о том, чтобы поместить его в синтаксический анализатор XML, который затем можно будет запросить для различных элементов.

Для спокойного и разумного обсуждения этой проблемы см. Этот классический пост stackoverflow: RegEx соответствует открытым тегам, за исключением автономных тегов XHTML .

Надеюсь, это поможет!

0 голосов
/ 07 октября 2010

java.util.regex не поддерживает бесконечное повторение внутри вид сзади

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