O chciwym kontra niechciwym
Powtórzenia w wyrażeniu regularnym są domyślnie zachłanne : starają się dopasować jak najwięcej powtórzeń, a kiedy to nie działa i muszą się cofać, próbują dopasować o jedno powtórzenie mniej na raz, aż dopasowanie całego wzorca jest znaleziony. W rezultacie, gdy w końcu dojdzie do meczu, chciwe powtórzenie będzie pasowało do jak największej liczby powtórzeń.
?
Jako powtórzenie kwantyfikator zmienia to zachowanie się nie chciwy , zwany też niechętnie ( w np Java ) (a czasem „leniwy”). W przeciwieństwie do tego powtórzenie najpierw spróbuje dopasować jak najmniejszą liczbę powtórzeń, a kiedy to nie zadziała i będą musieli się cofnąć, zaczną dopasowywać jeszcze jeden powtórzenie raz. W rezultacie, gdy w końcu dojdzie do meczu, niechętne powtórzenie będzie pasowało do jak najmniejszej liczby powtórzeń.
Bibliografia
Przykład 1: od A do Z
Porównajmy te dwa wzorce: A.*Z
i A.*?Z
.
Biorąc pod uwagę następujące dane wejściowe:
eeeAiiZuuuuAoooZeeee
Wzorce dają następujące dopasowania:
Najpierw skupmy się na tym, co A.*Z
robi. Kiedy pasował do pierwszego A
, .*
będąc chciwym, najpierw próbuje dopasować jak najwięcej .
.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
Ponieważ Z
nie pasuje, silnik cofa się, a .*
następnie musi dopasować o jeden mniej .
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
Dzieje się to jeszcze kilka razy, aż w końcu dojdziemy do tego:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
Teraz Z
można dopasować, więc ogólny wzorzec pasuje:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
Z drugiej strony niechętne powtarzanie w A.*?Z
pierwszych meczach .
jak najmniej, a następnie biorąc więcej .
w razie potrzeby. To wyjaśnia, dlaczego znajduje dwa dopasowania w danych wejściowych.
Oto wizualna reprezentacja dopasowania dwóch wzorców:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
Przykład: alternatywa
W wielu zastosowaniach dwa dopasowania w powyższym wejściu są pożądane, dlatego niechętny .*?
jest używany zamiast chciwego, .*
aby zapobiec nadmiernemu dopasowaniu. Jednak dla tego konkretnego wzorca istnieje lepsza alternatywa, używając klasy znaków zanegowanych.
Wzorzec A[^Z]*Z
znajduje również te same dwa dopasowania, co A.*?Z
wzorzec dla powyższego wejścia ( jak widać na ideone.com ). [^Z]
jest klasą znaków zanegowanych : pasuje do wszystkiego oprócz Z
.
Główna różnica między tymi dwoma wzorcami polega na wydajności: będąc bardziej rygorystycznym, klasa znaków zanegowanych może pasować tylko w jeden sposób dla danego wejścia. Nie ma znaczenia, czy użyjesz chciwego lub niechętnego modyfikatora dla tego wzorca. W rzeczywistości w niektórych smakach można zrobić jeszcze lepiej i użyć tak zwanego kwantyfikatora zaborczego, który w ogóle się nie cofa.
Bibliografia
Przykład 2: od A do ZZ
Ten przykład powinien być ilustracyjny: pokazuje, w jaki sposób zachłanne, niechętne i zanegowane wzorce klas znaków różnie pasują do tych samych danych wejściowych.
eeAiiZooAuuZZeeeZZfff
Oto dopasowania dla powyższego wejścia:
Oto wizualna reprezentacja tego, co dopasowali:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
powiązane tematy
Są to linki do pytań i odpowiedzi na temat stackoverflow, które obejmują niektóre interesujące tematy.
Jedno chciwe powtórzenie może przewyższyć inne