Różnica pomiędzy '.' , „?” i „*” w wyrażeniach regularnych?

21

Czy mogę uzyskać przykład różnic między tymi trzema elementami (czy są to tak zwane metaznaki?)?

Wiem, że *to znaczy wszystko albo nic, ale nie jestem pewien, czy to właściwy sposób, aby o tym myśleć. Z drugiej strony .i ?wydają się takie same. Pasują do jednej postaci, prawda?

posixKing
źródło
@Cyrus lub jeszcze lepiej: Dokumentacja Regex StackOverflow .
Thomas Ayoub,

Odpowiedzi:

16

Zaczerpnięte z Wikipedii :

? Znak zapytania wskazuje zero lub jedno wystąpienie poprzedniego elementu. Na przykład kolor pasuje do „koloru” i „koloru”.

*Gwiazdka wskazuje zero lub więcej wystąpień poprzedniego elementu. Na przykład ab * c pasuje do „ac”, „abc”, „abbc”, „abbbc” i tak dalej.

Duża różnica polega na tym, że gwiazdka odpowiada zeru lub większej liczbie wystąpień, podczas gdy znak zapytania odpowiada zeru lub jednemu wystąpieniu. Porównaj te dwa przykłady:

$ printf "colour\ncolor\ncolouur\n" | egrep 'colou?r'                          
colour
color
$ printf "colour\ncolor\ncolouur\n" | egrep 'colou*r'                          
colour
color
colouur

Ponieważ w colouurliterze u (poprzedni element przed kwalifikatorem ?) wystąpił więcej niż jeden raz, nie jest to zgodne z ?, ale jest dopasowane z*

Podobny przykład:

$ printf "error\neror\ner\n" | egrep 'er?or'                                   
eror
$ printf "error\neror\ner\n" | egrep 'er*or'                                   
error
eror

Z tej samej strony Wikipedii:

Odpowiada dowolnemu pojedynczemu znakowi (wiele aplikacji wyklucza znaki nowej linii, a to, które znaki są uważane za nowe linie, jest specyficzne dla smaku, kodowania znaków i specyficzne dla platformy, ale można bezpiecznie założyć, że znak wiersza jest uwzględniony). W wyrażeniach w nawiasach klamrowych POSIX znak kropki odpowiada dosłownej kropce. Na przykład ac pasuje do „abc” itp., Ale [ac] pasuje tylko do „a”, „.” Lub „c”.

W naszym przykładzie

$ printf "colour\ncolor\ncolouur\n" | egrep 'colo.r'                           
colour
$ printf "colour\ncolor\ncolouur\n" | egrep 'colou.r'                          
colouur

Właściwie ostatni z nich brzmi: match any line that has "colou", plus any character, plus letter "r"

Wniosek

Zapytałeś: „Wiem, że„ * ”oznacza wszystko albo nic, ale nie jestem pewien, czy to właściwy sposób myślenia o tym. Z drugiej strony”. I „?” wydaje się to samo. ” Jak widać kropka i gwiazdka nie są dokładnie takie same. Kropka działa na dowolny znak, który może zajmować tę konkretną pozycję, podczas gdy znak zapytania działa na poprzednim elemencie.

Sergiy Kolodyazhnyy
źródło
32

Możesz mylić wyrażenia regularne z globusami powłoki

W składni wyrażeń regularnych .reprezentuje dowolny pojedynczy znak (zwykle wykluczając znak nowej linii), podczas gdy *jest kwantyfikatorem oznaczającym zero lub więcej poprzedniego wyrażenia regularnego (znak lub grupa). ?jest kwantyfikatorem oznaczającym zero lub jedną instancję poprzedniego atomu, lub (w wariantach wyrażeń regularnych, które go obsługują) modyfikatorem, który ustawia zachowanie kwantyfikatora na niechciane.

W globusach powłoki ?reprezentuje pojedynczy znak (podobnie jak regex .), podczas gdy *reprezentuje sekwencję zero lub więcej znaków (odpowiednik regex .*).

Kilka odnośników, które mogą ci się przydać, to http://www.regular-expressions.info/quickstart.html i http://mywiki.wooledge.org/glob

steeldriver
źródło
6

Uwaga: Examples provided are in Python.Choć koncepcja pozostaje taka sama.

'.'jest pasującym symbolem, który pasuje do dowolnego znaku z wyjątkiem znaku nowej linii (to też można zastąpić re.DOTALLargumentem w Pythonie). Dlatego jest również nazywany symbolem wieloznacznym .

'*'jest kwantyfikatorem (określa, jak często może wystąpić element). Jest skrótem od {0,} .

Oznacza „dopasuj zero lub więcej” - grupa poprzedzająca gwiazdę może występować dowolną liczbę razy w tekście. Może być całkowicie nieobecny lub powtarzany w kółko.

'?'jest także kwantyfikatorem . Jest skrótem od {0,1} .

Oznacza to „Dopasuj zero lub jedną z grup poprzedzających ten znak zapytania”. Można to również zinterpretować, ponieważ część poprzedzająca znak zapytania jest opcjonalna .

na przykład:

pattern = re.compile(r'(\d{2}-)?\d{10}')
mobile1 = pattern.search('My number is 91-9999988888')
mobile1.group()
Output: '91-9999988888'

mobile2 = pattern.search('My number is 9999988888')
mobile2.group()
Output: '9999988888'

W powyższym przykładzie „?” oznacza, że ​​dwie poprzedzające ją cyfry są opcjonalne. Mogą się nie pojawić lub wystąpić jednorazowo.

Różnica pomiędzy '.' i '?':

'.'dopasowuje / akceptuje / weryfikuje dowolny pojedynczy znak dla miejsca, które zajmuje w wyrażeniu regularnym.

na przykład:

pattern = re.compile(r'.ot')
pattern.findall('dot will identify both hot and got.')
Output: ['dot', 'hot', 'got']

'?'dopasowuje / weryfikuje zerowe lub pojedyncze wystąpienie grupy poprzedzającej .

Sprawdź przykład numeru telefonu komórkowego.

To samo dotyczy '*'. Sprawdza zero lub więcej wystąpień grupy poprzedzającej .

Połączenie:

'.*': Akceptuje tyle sekwencji, ile jest dostępnych. Chciwe podejście .

'.*?„Akceptuje pierwszą dopasowaną sekwencję i zatrzymuje się. Nie chciwe podejście

Aby uzyskać więcej informacji, przeczytaj poniższe dwa pytania ...

Dhaval Simaria
źródło