Próbuję podzielić ciąg na dwie części za pomocą wyrażenia regularnego. Ciąg jest sformatowany w następujący sposób:
text to extract<number>
Używałem (.*?)<
i <(.*?)>
które działają dobrze, ale po lekkim przeczytaniu do wyrażenia regularnego zacząłem się zastanawiać, dlaczego potrzebuję ?
wyrażeń. Zrobiłem to dopiero po znalezieniu ich na tej stronie, więc nie jestem do końca pewien, na czym polega różnica.
Odpowiedzi:
To jest różnica między chciwymi i niechciwymi kwantyfikatorami.
Rozważ dane wejściowe
101000000000100
.Korzystanie
1.*1
,*
jest chciwy - będzie on pasował do końca do końca, a potem wracać, dopóki można go dopasować1
, pozostawiając Państwu1010000000001
..*?
nie jest chciwy.*
niczego nie dopasuje, ale spróbuje dopasować dodatkowe znaki, aż do dopasowania1
, ostatecznie dopasowując101
.Wszystkie kwantyfikatory posiada tryb non-chciwy:
.*?
,.+?
,.{2,6}?
, a nawet.??
.W twoim przypadku podobny wzorzec mógłby wyglądać
<([^>]*)>
- dopasowywanie czegokolwiek poza znakiem większości (ściśle rzecz biorąc, dopasowuje zero lub więcej znaków innych niż>
między<
i>
).Zobacz ściągawkę Quantifier .
źródło
?
różni się od niechciwego??
?"abc"
wyrażenie regularne/\w\w?\w/
będzie pasowało do pełnego ciągu"abc"
- ponieważ?
jest chciwe./\w\w??\w/
jest leniwy - będzie tylko pasował"ab"
. Wróci i dopasuje tylko"abc"
wtedy, gdy później zawiedzie.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
iA.*?Z
.Biorąc pod uwagę następujące dane wejściowe:
Wzorce dają następujące dopasowania:
A.*Z
daje 1 dopasowanie:AiiZuuuuAoooZ
( patrz rubular.com )A.*?Z
daje 2 dopasowania:AiiZ
iAoooZ
( zobacz na rubular.com )Najpierw skupmy się na tym, co
A.*Z
robi. Kiedy pasował do pierwszegoA
,.*
będąc chciwym, najpierw próbuje dopasować jak najwięcej.
.Ponieważ
Z
nie pasuje, silnik cofa się, a.*
następnie musi dopasować o jeden mniej.
:Dzieje się to jeszcze kilka razy, aż w końcu dojdziemy do tego:
Teraz
Z
można dopasować, więc ogólny wzorzec pasuje: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:
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, coA.*?Z
wzorzec dla powyższego wejścia ( jak widać na ideone.com ).[^Z]
jest klasą znaków zanegowanych : pasuje do wszystkiego opróczZ
.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.
Oto dopasowania dla powyższego wejścia:
A[^Z]*ZZ
daje 1 dopasowanie:AuuZZ
( jak widać na ideone.com )A.*?ZZ
daje 1 dopasowanie:AiiZooAuuZZ
( jak widać na ideone.com )A.*ZZ
daje 1 dopasowanie:AiiZooAuuZZeeeZZ
( jak widać na ideone.com )Oto wizualna reprezentacja tego, co dopasowali:
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
źródło
Powiedzmy, że masz:
<(.*)>
pasowałabya></a
tam, gdzie<(.*?)>
pasowałabya
. Ten ostatni zatrzymuje się po pierwszym meczu>
. Sprawdza, czy występuje jedno lub 0 dopasowań,.*
po którym następuje następne wyrażenie.Pierwsze wyrażenie
<(.*)>
nie kończy się na dopasowaniu do pierwszego>
. Będzie trwać do ostatniego meczu>
.źródło