2016-04-02 12 views
25

W poniższych przykładach (przez regex101.com, tryb PCRE), nie mogę zrozumieć, dlaczego kwantyfikator + znajdzie pod-ciąg znaków, ale * nie ma.Dlaczego * nie pasuje, gdy + robi?

W pierwszej ilustracji kwantyfikator + (jeden lub więcej), znajduje wszystkie cztery małymi do znaków (która jest, co spodziewane)

Plus-sign quantifier finds 1 or more as expected

W drugim rysunku, * kwantyfikator (0 lub więcej) nie znaleźliśmy żadnych małymi do znaków (co nie jest, czego się spodziewałem):

Asterisk quantifier doesn't find 0 or more

Co logika REGEX wyjaśnia, dlaczego "1 lub więcej" (+) znajduje wszystkie cztery małe małe litery: a, ale "0 lub więcej" (*) nie znajduje żadnego?

Odpowiedz

45

Silnik regex będzie próbował dopasować cały wzór w każdej pozycji w łańcuchu, od lewej do prawej. Wzorzec /a*/ pomyślnie dopasowuje zero na samym początku łańcucha. Oto, co oznacza mała kropkowana kreska na twoim zrzucie z regex101 - dopasowanie zerowej szerokości w tej pozycji. W tej pozycji pasowałoby więcej niż a, ale nie ma żadnych. Mimo to mecz się powiódł.

Jeśli używasz funkcji, która zwraca wszystkie dopasowania regex w łańcuchu, to przesunie się o co najmniej jeden znak za każdym razem, aby wyszukać nowe dopasowania, więc będzie pasować do aaaa (jako pojedynczego wyniku) po uzyskaniu do tego. Przykład w Pythonie:

import re 
regex = r"a*" 
input = "AAAAaaaaBBBBbbbb" 
print(re.findall(regex, input)) 

wyjściowa:

['', '', '', '', 'aaaa', '', '', '', '', '', '', '', '', ''] 

Zważywszy, że podczas korzystania /a+/, to nie może robić te zerowej szerokości mecze, więc kroki przez wejście aż znajdzie swój pierwszy i pasuje tylko do aaaa.

+0

To dziwne, że nie jest chciwy domyślnie, czy jest to konwencja? W Sublime pasuje do całej aaaa, chyba że robisz *? to się tak zachowuje. –

+12

Chciwy czy nie, "a *" dopasowuje zero wystąpienia "a" na początku łańcucha, więc dlaczego parser miałby wyglądać dalej? Nie wiem, co to jest "Sublime", ale brzmi to zepsute. – ghoti

+0

@ghoti to edytor tekstowy Windows/IDE, taki jak Notepad ++ (ale jest w 100% darmowy jak NP ++) ... ale brzmi też dla mnie źle: P. – RastaJedi

7

Właściwie pasuje do początku ciągu, w którym znajdują się zero a. Jeśli ciąg zaczyna się od a, pasuje do nich wszystkich.

9

Inne odpowiedzi już opisują, co się dzieje. Ale za to ilustracja/przykład tego spróbować na rozmiar:

$ echo AAAAaaaabbbb | egrep -o 'a*' && echo "SUCCESS" 

SUCCESS 

Efekt -o opcji grep jest pokazać tylko część wkładu, który pasował do wyrażenia regularnego. Ponieważ to, co pasowało, było "zero znaków", wynik jest pusty ... ale udany.

+2

Z jakiegoś powodu, gdy próbowałem tego (poprzez kopiowanie i wklejanie) na Mint Linux 17.3, egrep wyświetlił "aaaa" nad słowem SUCCESS – RBV

+1

@RBV - interesujące ... i nieoczekiwane. Nie widzę tego zachowania w grep BSD (opartym na GNU grep w wersji 2.5.1) w FreeBSD lub OSX, ale mogę potwierdzić podobne zachowanie do tego, co widzisz z GNU grep 2.5.4 w Ubuntu. Nie potrafię wyjaśnić tej niespójności między różnymi greps GNU. Jeśli wyszukasz hasło "z *", zobaczysz także SUKCES. – ghoti

+0

"ale mogę potwierdzić podobne zachowanie ..." Co w mojej głowie rodzi pytanie, które warianty egrep można lub nie można "ufać", aby zachowywać się w sposób przewidywalny. – RBV

3

Na początku możesz zobaczyć mecz!

What

Powiązane problemy