Odpowiedzi:
Najważniejszą częścią są koncepcje. Kiedy już zrozumiesz, jak działają elementy budulcowe, różnice w składni będą niewiele więcej niż łagodne dialekty. Warstwa nad składnią silnika wyrażeń regularnych to składnia używanego języka programowania. Języki, takie jak Perl, eliminują większość tej komplikacji, ale będziesz musiał pamiętać o innych kwestiach, jeśli używasz wyrażeń regularnych w programie C.
Jeśli myślisz o wyrażeniach regularnych jako elementach budulcowych, które możesz dowolnie mieszać i dopasowywać, pomoże Ci to nauczyć się pisać i debugować własne wzorce, ale także rozumieć wzorce napisane przez innych.
Koncepcyjnie najprostsze wyrażenia regularne to znaki dosłowne. Wzorzec N
pasuje do znaku „N”.
Wyrażenia regularne obok siebie dopasowują sekwencje. Na przykład wzorzec Nick
dopasowuje sekwencję „N”, po której następuje „i”, po którym następuje „c”, a następnie „k”.
Jeśli kiedykolwiek używałeś grep
w Uniksie - nawet jeśli tylko szukałeś zwyczajnie wyglądających łańcuchów - już używałeś wyrażeń regularnych! (Słowo re
in grep
odnosi się do wyrażeń regularnych).
Dodając tylko trochę złożoności, możesz dopasować do wzorca albo „Nick”, albo „nick” [Nn]ick
. Część w nawiasach kwadratowych jest klasą znaków , co oznacza, że pasuje dokładnie do jednego z zawartych w niej znaków. Możesz także używać zakresów w klasach znaków, więc [a-c]
dopasowuje albo „a”, „b”, albo „c”.
Wzorzec .
jest wyjątkowy: zamiast dopasowywać tylko literalną kropkę, dopasowuje dowolny znak † . Koncepcyjnie jest taki sam, jak naprawdę duża klasa postaci [-.?+%$A-Za-z0-9...]
.
Pomyśl o klasach postaci jak o menu: wybierz tylko jedną.
Używanie .
może zaoszczędzić wiele pisania, a istnieją inne skróty do typowych wzorców. Powiedzmy, że chcesz dopasować cyfrę: to jeden ze sposobów zapisu [0-9]
. Cyfry są częstym celem dopasowania, więc możesz zamiast tego użyć skrótu \d
. Inne to \s
(białe spacje) i \w
(znaki słowne: znaki alfanumeryczne lub podkreślenia).
Warianty pisane wielkimi literami są ich uzupełnieniami, więc \S
dopasowuje na przykład dowolny znak niebędący białą spacją.
Stamtąd możesz powtórzyć części swojego wzoru za pomocą kwantyfikatorów . Na przykład wzorzec ab?c
dopasowuje „abc” lub „ac”, ponieważ ?
kwantyfikator sprawia, że podwzór, który modyfikuje, jest opcjonalny. Inne kwantyfikatory to
*
(zero lub więcej razy)+
(raz lub więcej razy){n}
(dokładnie n razy){n,}
(co najmniej n razy){n,m}
(co najmniej n razy, ale nie więcej niż m razy)Łącząc ze sobą niektóre z tych bloków, wzór [Nn]*ick
pasuje do wszystkich
Pierwszy mecz to ważna lekcja: *
zawsze się udaje! Każdy wzorzec może pasować zero razy.
Kilka innych przydatnych przykładów:
[0-9]+
(i jego odpowiednik \d+
) pasuje do dowolnej nieujemnej liczby całkowitej\d{4}-\d{2}-\d{2}
pasuje do dat w formacie 01.01.2019Kwantyfikator modyfikuje wzorzec znajdujący się bezpośrednio po lewej stronie. Możesz spodziewać 0abc+0
się dopasowania „0abc0”, „0abcabc0” itd., Ale wzorzec bezpośrednio po lewej stronie kwantyfikatora plus to c
. Oznacza to, że 0abc+0
dopasowuje „0abc0”, „0abcc0”, „0abccc0” i tak dalej.
Aby dopasować jedną lub więcej sekwencji „abc” z zerami na końcach, użyj 0(abc)+0
. Nawiasy oznaczają wzór podrzędny, który można określić ilościowo jako jednostkę. Mechanizmy wyrażeń regularnych często zapisują lub „przechwytują” część tekstu wejściowego, która pasuje do grupy umieszczonej w nawiasach. Wyodrębnianie bitów w ten sposób jest znacznie bardziej elastyczne i mniej podatne na błędy niż liczenie indeksów i substr
.
Wcześniej widzieliśmy jeden sposób dopasowania „Nick” lub „nick”. Inny jest z naprzemiennością jak w Nick|nick
. Pamiętaj, że przemienność obejmuje wszystko po lewej stronie i wszystko po prawej stronie. Użyj grupowanie nawiasów w celu ograniczenia zakresu |
, na przykład , (Nick|nick)
.
W innym przykładzie można by równoważnie napisać [a-c]
jako a|b|c
, ale prawdopodobnie będzie to nieoptymalne, ponieważ wiele implementacji zakłada, że alternatywy będą miały długości większe niż 1.
Chociaż niektóre postacie pasują do siebie, inne mają specjalne znaczenie. Wzorzec \d+
nie pasuje do ukośnika odwrotnego, po którym następuje mała litera D, po której następuje znak plus: aby to uzyskać, użylibyśmy \\d\+
. Ukośnik odwrotny usuwa specjalne znaczenie z następującego znaku.
Kwantyfikatory wyrażeń regularnych są chciwe. Oznacza to, że dopasowują tyle tekstu, ile mogą, jednocześnie pozwalając na pomyślne dopasowanie całego wzorca.
Na przykład, powiedzmy, że wejście to
„Cześć”, powiedziała, „Jak się masz?”
Możesz spodziewać ".+"
się dopasowania tylko do „Hello”, a wtedy będziesz zaskoczony, gdy zobaczysz, że pasuje od „Hello” aż do „you?”.
Aby przełączyć się z zachłannych na ostrożne, dodaj ?
do kwantyfikatora jeszcze jeden. Teraz rozumiesz, jak \((.+?)\)
działa przykład z twojego pytania. Dopasowuje sekwencję dosłownego lewego nawiasu, po którym następuje jeden lub więcej znaków i kończy się prawym nawiasem.
Jeśli wprowadzisz „(123) (456)”, pierwsze przechwycenie będzie miało wartość „123”. Niechciane kwantyfikatory chcą, aby reszta wzorca zaczęła dopasowywać się tak szybko, jak to możliwe.
(Co do twojego pomieszania, nie znam żadnego dialektu wyrażeń regularnych, w którym ((.+?))
zrobiłoby to samo. Podejrzewam, że gdzieś po drodze coś zgubiło się podczas transmisji.)
Użyj specjalnego wzorca, ^
aby dopasować tylko na początku wprowadzania i $
dopasować tylko na końcu. Wykonywanie „podpórek” z własnymi wzorami, w których mówisz: „Wiem, co jest z przodu iz tyłu, ale daj mi wszystko pomiędzy” jest przydatną techniką.
Powiedz, że chcesz dopasować komentarze w formularzu
-- This is a comment --
napisałbyś ^--\s+(.+)\s+--$
.
Wyrażenia regularne są rekurencyjne, więc teraz, gdy rozumiesz te podstawowe zasady, możesz je łączyć w dowolny sposób.
†: Powyższe stwierdzenie, które .
pasuje do dowolnego znaku, jest uproszczeniem ze względów pedagogicznych, które nie jest do końca prawdziwe. Kropka pasuje do dowolnego znaku poza "\n"
nową linią, ale w praktyce rzadko spodziewasz się, że wzorzec, na przykład .+
przekroczy granicę nowej linii. Na przykład wyrażenia regularne Perla mają /s
przełącznik i Javę Pattern.DOTALL
, aby w .
ogóle dopasować dowolny znak. W przypadku języków, które nie mają takiej funkcji, możesz użyć czegoś takiego, jak [\s\S]
„dowolna spacja lub dowolna inna spacja”, innymi słowy cokolwiek.
a{,m}
nie jest rzeczą, przynajmniej w Javascript, Perl i Pythonie.