Czy ktoś mógłby wyjaśnić te dwa pojęcia w zrozumiały sposób?
regex
regex-greedy
non-greedy
ajsie
źródło
źródło
Odpowiedzi:
Chciwi pochłoną jak najwięcej. Na stronie http://www.regular-expressions.info/repeat.html widzimy przykład próby dopasowania tagów HTML
<.+>
. Załóżmy, że masz:Możesz myśleć, że
<.+>
(.
środki jakikolwiek zakaz znak nowej linii i+
środki jedna lub więcej ) będzie pasować tylko<em>
a</em>
, podczas gdy w rzeczywistości będzie bardzo chciwy i przejść od pierwszego<
do ostatniego>
. Oznacza to, że będzie pasować<em>Hello World</em>
zamiast tego, co chcesz.Lazy (
<.+?>
) zapobiegnie temu. Dodając?
po+
, mówimy, aby powtarzał się tak mało, jak to możliwe , więc po raz pierwszy>
pojawia się, gdy chcemy zatrzymać dopasowanie.Zachęcam do pobrania RegExr , świetnego narzędzia, które pomoże ci odkrywać wyrażenia regularne - używam go cały czas.
źródło
<[^>]+>
obejście tego„Chciwy” oznacza dopasowanie najdłuższego możliwego ciągu.
„Leniwy” oznacza dopasowanie możliwie najkrótszego ciągu.
Na przykład, chciwych
h.+l
mecze'hell'
w'hello'
ale leniweh.+?l
mecze'hel'
.źródło
h.+l
mecze'helol'
w'helolo'
ale leniweh.+?l
mecze'hel'
.x?
Oznacza, żex
jest opcjonalny, ale+?
ma inną składnię. Oznacza to, że przestaniesz szukać czegoś, co pasuje - leniwe dopasowanie.?
oznacza opcjonalne i+?
oznacza leniwe. Dlatego\+?
środki+
są opcjonalne.Przykład:
łańcuch testowy: stackoverflow
greedy reg expression :
s.*o
output: stackoverflo wlazy reg expression :
s.*?o
output: stacko verflowźródło
re.match('(f)?(.*)', 'food').groups()
zre.match('(f)??(.*)', 'food').groups()
. W tym drugim(f)??
przypadku nie będzie pasować do wiodącego „f”, chociaż może. Dlatego „f” zostanie dopasowane do drugiej grupy przechwytywania „. *”. Jestem pewien, że możesz skonstruować przykład za pomocą „{n}?” też. Trzeba przyznać, że te dwa są bardzo rzadko używane.Chciwy oznacza, że twoje wyrażenie będzie pasować do jak największej grupy, leniwy oznacza, że pasuje do najmniejszej możliwej grupy. Dla tego ciągu:
i to wyrażenie:
Chciwy mecz pasuje do całego ciągu, a leniwy mecz pasuje tylko do pierwszego
abc
.źródło
O ile mi wiadomo, większość silników wyrażeń regularnych jest domyślnie zachłanna. Dodaj znak zapytania na końcu kwantyfikatora umożliwi leniwe dopasowanie.
Jak wspomniano w komentarzu @Andre S.
Poniższy przykład pokazuje, co jest chciwe, a co leniwe.
Wynik to:
źródło
Zaczerpnięte z www.regular-expressions.info
Greediness : Greedy kwantyfikatorów próbuje najpierw powtórzyć token tyle razy, ile to możliwe, i stopniowo rezygnuje mecze jako cofa silników znaleźć ogólną mecz.
Lenistwo : Leniwy kwantyfikator najpierw powtarza token tyle razy, ile potrzeba, i stopniowo rozszerza dopasowanie, gdy silnik cofa się przez wyrażenie regularne, aby znaleźć ogólne dopasowanie.
źródło
Z wyrażenia regularnego
źródło
Chciwe dopasowanie. Domyślne zachowanie wyrażeń regularnych jest zachłanne. Oznacza to, że próbuje wyodrębnić jak najwięcej, dopóki nie dopasuje się do wzoru, nawet jeśli mniejsza część byłaby wystarczająca składniowo.
Przykład:
Zamiast dopasowywać do pierwszego wystąpienia „>”, wyodrębnił cały ciąg. Jest to domyślne zachowanie wyrażenia chciwego lub „bierz wszystko”.
Z drugiej strony, leniwe dopasowywanie „zajmuje jak najmniej”. Można tego dokonać dodając
?
na końcu wzoru.Przykład:
Jeśli chcesz pobrać tylko pierwsze dopasowanie, użyj metody wyszukiwania.
Źródło: Przykłady Python Regex
źródło
Chciwy oznacza, że pochłonie twój wzór, dopóki nie pozostanie żaden z nich i nie będzie mógł szukać dalej.
Leniwy zatrzyma się, gdy tylko napotka pierwszy żądany wzór.
Jednym z często spotykanych przykładów jest
\s*-\s*?
regex([0-9]{2}\s*-\s*?[0-9]{7})
Pierwszy
\s*
jest klasyfikowany jako zachłanny, ponieważ*
po napotkaniu cyfr będzie wyglądał jak najwięcej białych znaków, a następnie będzie szukał znaku myślnika „-”. Gdzie jako drugi\s*?
jest leniwy z powodu teraźniejszości,*?
co oznacza, że będzie wyglądał pierwszy biały znak i zatrzyma się właśnie tam.źródło
Najlepiej pokazuje to przykład. Strunowy.
192.168.1.1
i zachłanna regex\b.+\b
Możesz pomyśleć, że to da ci pierwszy oktet, ale w rzeczywistości pasuje do całego łańcucha. Dlaczego? Ponieważ. + Jest zachłanny, a zachłanne dopasowanie pasuje do każdego znaku,192.168.1.1
dopóki nie osiągnie końca łańcucha. To jest ważny kawałek! Teraz zaczyna cofać się jedna postać na raz, dopóki nie znajdzie dopasowania dla 3. tokena (\b
).Jeśli na początku był plik tekstowy o wielkości 4 GB i 192.168.1.1, można łatwo zobaczyć, w jaki sposób to cofnięcie spowodowałoby problem.
Aby regex nie był chciwy (leniwy), po wyszukiwaniu chciwego umieść znak zapytania, np
To, co się teraz dzieje, to
+?
znalezienie tokena 2 ( ), wyrażenie regularne przesuwa się wzdłuż znaku, a następnie wypróbowuje następny token (\b
) zamiast tokena 2 (+?
). Więc ostrożnie się skrada.źródło
Chciwi kwantyfikatory są jak IRS / ATO: biorą tyle, ile mogą:
Jeśli tam jest, przyjdą i zabiorą go. Zabiorą to wszystko:
Na przykład IRS pasuje do tego wyrażenia regularnego:
.*
$50,000
- IRS to wszystko. Ci chciwi.*{4}?
ludzieZobacz tutaj przykład: regexr.com/4t27f
Nie chciwi kwantyfikatory - zabierają tak mało, jak to możliwe
Z drugiej strony, jeśli poproszę o zwrot podatku, IRS nagle staje się niechciany i używają tego kwantyfikatora:
(.{2}?)([0-9]*)
przeciw temu wyrażeniu:$50,000
Pierwsza grupa jest niepotrzebna i pasuje tylko$5
- więc dostaję$5
zwrot pieniędzy. Resztę zabiera wujek Sam na marnotrawstwo.Zobacz tutaj: Nie-chciwy przykład .
Po co się męczyć?
Staje się to ważne, jeśli próbujesz dopasować pewne części wyrażenia. Czasami nie chcesz dopasować wszystkiego.
źródło
spróbuj zrozumieć następujące zachowanie:
źródło