В регулярном выражении Python я сталкиваюсь с этой особой проблемой. Не могли бы вы дать инструкцию о различиях между re.findall('(ab|cd)', string)
и re.findall('(ab|cd)+', string)
?
import re
string = 'abcdla'
result = re.findall('(ab|cd)', string)
result2 = re.findall('(ab|cd)+', string)
print(result)
print(result2)
Фактический результат:
['ab', 'cd']
['cd']
Я не понимаю, почему второй результат также не содержит 'ab'
?
Ответы:
+
является повторным квантификатором, который соответствует одному или нескольким разам. В регулярном выражении(ab|cd)+
вы повторяете группу захвата,(ab|cd)
используя +. Это будет захватывать только последнюю итерацию.Вы можете рассуждать об этом поведении следующим образом:
Скажите, что ваша строка
abcdla
и регулярное выражение есть(ab|cd)+
. Движок Regex найдет совпадение для группы между позициями 0 и 1ab
и выйдет из группы захвата. Затем он видит+
квантификатор и пытается снова захватить группу и захватываетcd
между позициями 2 и 3.Если вы хотите захватить все итерации, вы должны захватить повторяющуюся группу, с
((ab|cd)+)
которой совпадаетabcd
иcd
. Вы можете запретить захват внутренней группы, так как нам не нужны совпадения внутренней группы с((?:ab|cd)+)
какими совпадениямиabcd
https://www.regular-expressions.info/captureall.html
Из документов,
источник
'(?:ab|cd)+'
будет работать.Я не знаю, если это прояснит ситуацию больше, но давайте попробуем представить, что происходит под капотом, простым способом, мы собираемся суммировать, что происходит с помощью матча
findall
сопоставить и использовать строку одновременно, давайте представим, что происходит с этим REGEX'(ab|cd)'
:Теперь то же самое с
'(ab|cd)+'
Я надеюсь, что это немного прояснит ситуацию.
источник
Итак, для меня запутанной частью был тот факт, что
документы
так что он возвращает вам не полное совпадение, а только совпадение захвата. Если вы сделаете эту группу не захватывающей
(re.findall('(?:ab|cd)+', string)
, она вернется,["abcd"]
как я и ожидалисточник