W wyrażeniu regularnym Python napotykam ten szczególny problem. Czy możesz podać instrukcje dotyczące różnic między re.findall('(ab|cd)', string)
i 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)
Rzeczywista wydajność wynosi:
['ab', 'cd']
['cd']
Jestem zdezorientowany, dlaczego drugi wynik również nie zawiera 'ab'
?
Odpowiedzi:
+
to powtarzalny kwantyfikator, który pasuje jeden lub więcej razy. W regex(ab|cd)+
, jesteś powtarzając grupę przechwytywania(ab|cd)
za pomocą +. To uchwyci tylko ostatnią iterację.Możesz uzasadnić to zachowanie w następujący sposób:
Powiedz, że twój ciąg to
abcdla
i wyrażenie regularne(ab|cd)+
. Silnik Regex znajdzie dopasowanie dla grupy między pozycjami 0 i 1ab
i opuszcza grupę przechwytywania. Następnie widzi+
kwantyfikator i próbuje ponownie przejąć grupę i przechwycicd
między pozycjami 2 i 3.Jeśli chcesz przechwycić wszystkie iteracje, powinieneś przechwycić powtarzającą się grupę, z
((ab|cd)+)
którą pasujeabcd
icd
. Możesz sprawić, że grupa wewnętrzna nie będzie przechwytywana, ponieważ nie dbamy o mecze grupy wewnętrznej, z((?:ab|cd)+)
którymi meczeabcd
https://www.regular-expressions.info/captureall.html
Z Dokumentów,
źródło
'(?:ab|cd)+'
zadziała.Nie wiem, czy to rozwiąże więcej, ale spróbujmy sobie wyobrazić, co dzieje się pod maską w prosty sposób, podsumujemy to, co się stanie, używając dopasowania
findall
dopasuj i zużyj ciąg w tym samym czasie wyobraźmy sobie, co się stanie z REGEX'(ab|cd)'
:Teraz to samo z
'(ab|cd)+'
Mam nadzieję, że to trochę wyjaśni.
źródło
Więc dla mnie mylące było to, że
dokumenty
więc nie zwraca pełnego dopasowania, a jedynie dopasowanie do przechwytywania. Jeśli
(re.findall('(?:ab|cd)+', string)
sprawisz , że ta grupa nie będzie przechwytywać , wróci,["abcd"]
jak początkowo oczekiwałemźródło