Coś, co jest tak zakręcone, nie powinno się nazywać "regularne"

Do końca tej strony będę używać takiej konwencji: wyrażenie regularne i ciąg znaków, do którego wrażenie pasuje. A zanim zaczniesz wypróbowywać wyrażenia w Vim-ie czy w grep-ie, przeczytaj komentarz z dołu stronki
Wyrażenie regularne to inaczej taki ciąg znaczków, że pewne inne ciągi (niekoniecznie takie same) pasują do niego. Konkretnie do ciągu [a-cw]*b+((ch)|(rz))?a.{2,4} może podpasować słowo wrzask, podobnie z resztą, jak ccabbbcbbaopp Fajne, co?
Zaczniemy od najprostszych wyrażeń (czy byłby sens zaczynać od najtrudniejszych? :) ). Samo słowo, bez żadnych przecinków, nawiasów, gwiazdek, plusów, pytajników i innych znaków przestankowych, tylko litery, cyfry i spacja - oto najprostsze, co może być. Takie coś pasuje samo siebie (czyli czasownik pasuje do słowa czasownik i tylko do niego). Rozszerzmy teraz naszą wiedzę conieco: gwiazdka *, pytajnik ? i plus + mają specjalne znaczenie. Jeśli gwiazdka będzie występować za literką (powiedzmy) s, to takie coś pasuje do braku s, do jednego s, do dwóch, trzech... do tylu, ile się tylko da: w wyrażeniu ja sobie hopsasasa do lassa do maski s*a dopasowane zostaną a z wyrazu ja, wszystkie sa w trzecim wyrazie, pojedyncze a i ssa w drugim. Pytajnik z kolei pasuje do literki lub jej braku: maska k?toś spasuje w wyrażeniu ktoś sobie toś ttoś podpasuje wyrazy ktoś i toś i trzy ostatnie litery z ostatniego wyrazu. Drugie t nie zostanie włączone do tego, co pasuje. Plus z kolei działa tak: w+erty w wyrażeniu wwwwwwerty erty werty dopasuje wyrazy pierwszy i trzeci, drugiego nie ruszając. Toto działa jak ww*erty. Pasuje co najmniej jedną literkę, próbując trafić jak najwięcej. Jeśli chcesz trafić samą gwiazdkę, plus czy pytajnik, to poprzedź go/ją backslashem.
Weźmy teraz na warsztat nawiasy klamrowe {}. Te mają dość fajne zastosowanie: x{2,5} pasuje literkę x występującą od 2 do 5 razy, przy czym im więcej razy występuje, tym lepiej. To jest równoważne wyrażeniu xxx?x?x?. Można trafiać jak najmniej literek: x{-2,5} pasuje tak, jak wyżej, z tym że raczej stara się trafić mniej literek (niestety, nie ma przykładu na to dla pojedynczych liter, musiałbyś znać nieco więcej). Jak chcesz trafić dokładnie pięć literek z, to możesz wstawić zzzzz (co jest najprostszym wyjściem dla samych liter, ale nie zdaje egzaminu przy bardziej złożonych wyrażeniach), albo możesz wybrać z{5}. Możesz jeszcze pominąć początkową liczbę przy zakresie ilości trafień, wtedy trafiasz od 0 do tylu, ile wpisałeś, albo możesz pominąć końcową liczbę - trafiasz co najmniej tyle, ile wpisałeś. W szczególności q{1,} jest równoważne z q+, a q{,1} = q? Fajne jest też w{-1,} trafiające literki w, ale zaznaczające jak najmniej (to również jest przydatne w bardziej skomplikowanych wyrażeniach). Identyczna sytuacja, jak przy *?+ : jak chcesz trafić sam nawias klamrowy, poprzedź go backslashem (i przedwias, i zawias, o ile użyłeś obu)
No to pora na nawiasy kwadratowe [] i znaczek | (symbol potoku, [Shift+\]). Znaczek | mówi, że ma zostać trafione albo to, co stoi przed nim, albo to, co stoi za nim, tzn. łoś|m trafi w łoś ma w swoim posiadaniu łom wyrazy pierwszy i ostatni. Natomiast nawiasy kwadratowe trafiają jeden znaczek z pewnej klasy. Te klasy definiuje się w taki sposób: zwykła literka lub cyferka mówi o samej sobie, minus mówi o zakresie. [a-c] z początkowego wyrażenia trafia na jeden ze znaczków pomiędzy a i c (czyli a, b lub c). Żeby trafić sam minus, umieść go albo na początku klasy, albo na końcu: [-a-zAEIOUY] trafia minus, dowolną małą literę lub dużą samogłoskę. Żeby trafić cokolwiek, tylko nie tą klasę, wstaw na początku daszek ^: [^aeiouyAEIOUY] trafia cokolwiek, tylko nie samogłoskę. Żeby wpasować nawias kwadratowy (którykolwiek), umieść go w klasie na początku albo na końcu. Jeśli nie chesz tworzyć całej klasy, po prostu poprzedź go backslashem (podobnie znaczek potoku). Tak w ogóle, to jakikolwiek znaczek traci swoje specjalne znaczenie, gdy zostanie poprzedzony backslashem. I jeszcze trick: klasa wszystkich znaków drukowalnych (w tym spacji i tabulacji) ma skrót: kropkę. Zatem .{3} pasuje trzy dowolne znaki.
Co może cię jeszcze zainteresować, to nawiasy okrągłe (). Domyślasz się, że zespalają one kilka fragmentów wyrażenia regularnego w jedną całość: (test)|(pies) szuka dowolnego z wyrazów test i pies, a (as)+ trafia ciągi as, asas, asasasasas i tym podobne. Oczywiście możesz wewnątrz nawiasu wstawić dowolnie skomplikowane wyrażenie.
Ostatnie ciekawe są dolar $ i daszek ^ (tym razem nie w klasie). Dolar użyty na końcu wyrażenia przyczepia je do końca linii, daszek na początku wyrażenia przyczepia je do początku linii. Dzięki temu ^test trafi tylko na te słowa test, które są na początku linii, a już tych dalszych nie, a ^jedyny tekst w linii$ trafi w zdanie jedyny tekst w linii, które musi samo w linii.
Specyficzne dla poszczególnych programów jest traktowanie sekwencji escape'owych, takich jak \n czy \t. Czasem (vim, ex) się tego używa, a czasem (grep, sed) - nie. Najlepiej poczytaj dokumentację i popróbuj sam. A po więcej informacji o wyrażeniach regularnych odsyłam do dokumentacji grepa, perla, vima (tutaj wbudowany help, nie manual) i czego tylko masz zamiar używać co obsługuje wyrażenia regularne. Tylko że najprawdopodobniej dodatkowe sztuczki nie będą działać gdzie indziej.


Słówko komentarza: W różnych programach korzystających z wyrażeń regularnych niekiedy backslashem włącza się specjalne traktowanie niektórych znaków specjalnych, np. w sedzie, vimie i grepie żeby trafiać jeden lub więcej znaków, trzeba wstawić \+ zamiast pojedynczego +, podobnie jak nawiasy klamrowe {}, zwykłe () czy znaczek potoku |. Musisz sam popróbować, co jest jak traktowane.


Kurs Bash-a
Indeks strony