Поиск назад регулярного выражения не работает с квантификаторами ('+' или '*')

Я пытаюсь использовать ретроспективный поиск в регулярном выражении, и это не работает так, как я ожидал. Итак, это не мое реальное использование, но для упрощения я приведу пример. Представьте, что я хочу сопоставить «пример» со строкой, в которой говорится «это пример». Итак, в соответствии с моим пониманием просмотра назад, это должно сработать:

(?<=this\sis\san\s*?)example

При этом нужно найти «this is an», затем пробел и наконец сопоставить слово «example». Теперь это не работает, и я не понимаю, почему, невозможно использовать '+' или '*' внутри ретроспективного обзора?

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

(?<=this\sis\san\s)example
this\sis\san\s*?example

Я использую этот сайт для проверки своих регулярных выражений: http://gskinner.com/RegExr/

27
задан Noel De Martin 27 January 2012 в 07:45
поделиться

5 ответов

Многие библиотеки регулярных выражений допускают использование только строгих выражений при проверке утверждений вроде:

  • соответствуют только строкам одинаковой фиксированной длины: (?<=foo|bar|\s,\s) (по три символа в каждой)
  • соответствуют только строки фиксированной длины: (?<=foobar|\r\n) (каждая ветвь с фиксированной длиной)
  • соответствуют только строки с верхней границей длины: (?<=\s{,4}) (до четырех повторений)

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

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

См. Также раздел об ограничениях проверочных утверждений на Regular-Expressions.info .

29
ответ дан 28 November 2019 в 05:15
поделиться

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

Этот сайт объясняет это хорошо. http://www.phpfreaks.com/blog/pcre-regex-spotlight-k ..

Но в значительной степени, когда у вас есть выражение, которое вы соответствуете, и вы хотите получить все, что позади него, с помощью \ K заставит его начать все сначала ...

Пример:

string = '<a this is a tag> with some information <div this is another tag > LOOK FOR ME </div>'

совпадение /(\<a).+?(\<div).+?(\>)\K.+?(?=\<div)/ будет заставьте регулярное выражение перезапускаться после совпадения с конечным тегом div, чтобы регулярное выражение не включало его в результат. (?=\div) заставит движок получить все перед конечным тегом div

12
ответ дан 28 November 2019 в 05:15
поделиться

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

(?<=this\sis\san)(?:\s*)example

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

5
ответ дан 28 November 2019 в 05:15
поделиться

Большинство движков регулярных выражений не поддерживают выражения переменной длины для проверочных утверждений.

0
ответ дан 28 November 2019 в 05:15
поделиться

Вы можете использовать подвыражения.

(this\sis\san\s*?)(example)

Таким образом, чтобы получить группу 2, «пример», $2 для регулярного выражения или \2, если вы используете строку формата (например, для Python re.sub)

0
ответ дан 28 November 2019 в 05:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: