Нежадный в Python Regex

Я пытаюсь понять нежадное регулярное выражение в python, но я не понимаю, почему следующие примеры имеют такие результаты:

print(re.search('a??b','aaab').group())
ab
print(re.search('a*?b','aaab').group())
aaab

Я думал, что это будет «b» для первого и «ab» для второго. Кто-нибудь может это объяснить?


person marylein    schedule 11.07.2015    source источник
comment
Причина в том, что механизм регулярных выражений анализирует строку слева направо и возвращает первое возможное совпадение в крайнем левом положении. Тот факт, что вы используете нежадный квантификатор, ничего не меняет.   -  person Casimir et Hippolyte    schedule 11.07.2015


Ответы (3)


Это происходит потому, что совпадения, которые вы запрашиваете, совпадают потом. Если вы попытаетесь проследить, как происходит сопоставление для a??b слева направо, вы увидите что-то вроде этого:

  • Попробуйте 0 a плюс b против aaab: совпадений нет (b != a)
  • Попробуйте 1 a плюс b против aaab : совпадений нет (ab != aa)
  • Попробуйте 0 a плюс b против aab: совпадения нет (b != a) (позиция совпадения сдвинута вправо на единицу)
  • Попробуйте 1 a плюс b против aab : совпадений нет (ab != aa)
  • Попробуйте 0 a плюс b против ab: совпадения нет (b != a) (позиция совпадения сдвинута вправо на единицу)
  • Попробуйте 1 a плюс b против ab : сопоставьте (ab == ab)

Аналогично для *?.

Дело в том, что функция search возвращает крайнее левое совпадение. Использование ?? и *? изменяет только поведение, предпочтя кратчайшее левое совпадение, но оно не возвращает более короткое совпадение, которое начинается справа от уже найденного совпадения.

Также обратите внимание, что модуль re не возвращает перекрывающихся совпадений, поэтому, даже используя findall или finditer, вы не сможете найти два искомых совпадения.

person Bakuriu    schedule 11.07.2015

Это связано с тем, что ?? является ленивым, а ? является жадный. И ленивый квантификатор будет соответствовать нулю или единице (его левый токен), нулю, если это все еще позволяет соответствовать общему шаблону. Например, все следующее вернет пустую строку:

>>> print(re.search('a??','a').group())

>>> print(re.search('a??','aa').group())

>>> print(re.search('a??','aaaa').group())

И регулярное выражение a??b будет соответствовать ab или b :

>>> print(re.search('a??b','aaab').group())
ab
>>> print(re.search('a??b','aacb').group())
b

И если это не позволяет совпадать с общим шаблоном и не было никакого b, он вернет None :

>>> print(re.search('a??b','aac').group())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'

А что касается второй части, у вас есть нежадное регулярное выражение, и результат очень очевиден. Он будет соответствовать любому количеству a, а затем b:

print(re.search('a*?b','aaab').group())
aaab
person kasravnd    schedule 11.07.2015

Объяснение шаблона - /a??b/

a?? соответствует символу a буквально (с учетом регистра), тогда квантификатор ?? означает от нуля до одного раза, как можно меньше раз, расширяясь по мере необходимости [ленивый], тогда символ b должен совпадать буквально (с учетом регистра)

Таким образом, он будет соответствовать последним 'ab' символам в данной строке 'aaab'

И для узора - /a*?b/

a*? соответствует символу 'a' буквально (с учетом регистра) Здесь квантификатор *? означает от нуля до неограниченного количества раз, как можно меньше раз, расширение по мере необходимости [ленивый], тогда символ b должен соответствовать буквально (с учетом регистра).

Таким образом, он будет соответствовать 'aaab' в целом в 'aaab'.

person kvivek    schedule 11.07.2015