Wyrażenia regularne typu PERL

Wyrażenie regularne jest to sposób zapisu pewnego ciągu składającego się ze znaków oraz metaznaków, które pełnią odpowiednią funkcję. Ciąg taki to wzorzec, który opisuje łańcuch symboli. Celem zabiegu jest sformatowanie takiego wzorca, aby tekst poddawany dopasowaniu odpowiadał mu.
Przykładem zastosowania może być sprawdzenie poprawności kodu pocztowego, który składa się z dwóch cyfr, myślnika a po nim następujących trzech cyfr (np. 03-111). Porównując taki kod bez wyrażenia z odpowiednim wzorcem dopasujemy tylko konkretny przypadek, np. 03-111 musi sie równać 03-111 i wtedy będzie tylko pasował.
Stosując wyrażenia regularne możemy określić wzorzec dla kodu pocztowego i będzie on dopasowany do każdego zapisanego kodu pocztowego i tylko do niego. Przykład:

^\d{2}-\d{3}$

Jak widać, wzorzec składa się z pewnych symboli, które mają pewne znaczenie w wyrażeniach regularnych. I tak "^" oznacza początek badanego ciągu znaków, "\d" jest skróconym zapisem mówiącym, że tutaj powinna zostać podana cyfra z zakresu 0-9. Natomiast nawiasy klamrowe i w nim zawarta liczba określa ile takich cyfr w ciągu ma się powtarzać.
Myślnik nie ma żadnego znaczenia jako metaznak, natomiast określa dosłownie konkretny znak.

Metaznaki
To zbiór znaków, które mają pewne znaczenie w wyrażeniach regularnych:

. ^ $ * + ? { } [ ] \ | ( )

"." (kropka) - oznacza dowolny znak, prócz znaku nowego wiersza (\n), np.: ".ot". Badany wyraz może pasować do np. pot, Pot, kot, Kot. Przed "ot" musi wystąpić dowolny znak (nawet spacja, przecinek itp.), prócz znaku nowej linii.

"[]" - para nawiasów kwadratowych sluży, aby określić jakiś jeden znak, który będzie pasował do zakresu znaków w nawiasach. Na przykład "[azsd]", ciąg będzie pasował jeżeli wystąpi litera a, z, s lub d. Dodatkowo w nawiasach stosuje się znak specjalny "-" (myślnik), aby wprowadzić pewien zakres znaków, np. "a-z" (znaki od a do z). Dodatkowo można zanegować zbiór znaków (te znaki nie mogą wystąpić) poprzez dodanie daszka "^" po otwarciu nawiasu. Przykłady:

[a-h2-4] - musi wystąpić znak z zakresu liter od a do h lub cyfr od 2 do 4.
Ma[rp]iusz - ciąg może pasować do słowa "Mariusz" lub "Mapiusz"
Kat[1-38] - wyrażenie będzie pasowało dla "Kat1", "Kat2", "Kat3" i "Kat8" (zapis "1-38" nie oznacza zakresu od 1 do 38. Oznacza zakres od 1 do 3 oraz do tego może wystąpić 8)
PK[^P] – Będzie pasowało do ciągu typu PKS, PKN, PKL. Natomiast nie zostanie dopasowane do PKP (ostatnie P nie może wystąpić)

"^" i "$" - znaki te stosuje się, aby określić początek i koniec ciągu, np.:

"^kto$", będzie pasował dla ciągu "kto", ale już nie dla "ktoś" lub " kto" (znak spacji przed k).

Dodatkowo znak "^" wykorzystywany jest aby zrobić negacje w nawiasach kwadratowych, co zostało opisane wyżej.

"( )" - para nawiasów okrągłych, służy do określenia grupy/podgrupy i wyróżnienia danego kawałka zbioru. Tekst w nawiasach będzie w wyniku jako kolejna część. Np.:

/Jakiś (tekst)/ - jeżeli wyrażenie pasuje, wynikiem będzie tablica o dwóch indeksach. Pierwszy (zerowy) należny zawsze do całego wyrażenia, czyli:

Jakiś tekst

Następny indeks to kolejny ciąg w nawiasach, czyli:

tekst

Dodatkowo do nawiasów stosowana jest znak specjalny "|" (kreska pionowa), która oznacza alternatywę. Przykład:

"^skok (na|do) bank"

wyrażenie będzie prawidłowe dla "skok na bank", jak i również dla "skok do bank". Ale już nie będzie prawidłowe dla "to był skok na bank". Dlaczego? Dlatego, że przed zdaniem stoi specjalny znak "^", który oznacza początek zdania i przez to nic przed "skok" nie może się znajdować.

"\" - backslash, służy do zamiany, aby znaki specjalne były traktowane jako część tekstu, np.:

"x + y\(x \* y\)" - nawiasy i gwiazdka będą traktowane jako standardowa część łańcucha a nie jako metaznak.

"*" - oznacza zakres znaku, który stoi przed gwiazdką. Znak ten oznacza zakres od 0 do nieskończoności. Przykład:

"Web*Reklama" - łańcuch będzie pasował dla "WebReklama" jak i "WebbbbbReklama". Ale należy też zwrócić uwagę, że słowo "WeReklama", też będzie pasowało, gdyż gwiazdka oznacza od zera. Czyli "b" nie musi wcale występować.

"+" - oznacza zakres od 1 do nieskończoności:

Stro+ny = pasuje dla: "Strony", "Stroooony", ale nie pasuje już dla "Strny", gdyż musi być przynajmniej jeden taki znak, który występuje przed plusem.

"?" - oznacza ograniczenie od 0 do 1. Ale znak zapytania ma jeszcze inne zastosowania, które zostanie omówione dalej.

"{ }" - w klamrach możemy założyć własne ograniczenia zakresów znaków. I tak:

{1} oznacza dokładnie tylko jedno powtórzenie.
{2,5} oznacza zakres od 2 do 5
{3,} oznacza zakres od 3 do nieskończoności.

W wyrażeniach regularnych możemy się wspomóc tez pewnymi klasami, które nam mogą skrócić zapisywanie pewnych zakresów znaków. I są to:

\d => to samo co [0-9] - zakres cyfr od 0 do 9
\D => to samo co [^0-9] - wszystkie znaki, prócz cyfr.
\w => to samo co [a-zA-Z0-9_] - wszystko co jest literą, cyfrą lub podkreślnikiem „_".
\W => to samo co [^a-zA-Z0-9_] - negacja powyższego przykładu.
\s => to samo co [\r\t\n\f] - dowolny odstęp (białe znaki).
\S => to samo co [^\r\t\n\f] - nie mogą występować dowolne odstępy.

Inne znaczenia znaku zapytania.

(?=...) dany ciąg znaków będzie pasował, gdy po zadanym ciągu będzie się znajdował ciąg w nawiasach, np.:

hello(?= world) - tekst hello będzie pasował tylko, gdy po nawiasie wystąpi [spacja]world, czyli "hello world"

(?!...) to co wyżej, tylko nie może wystąpić dany ciąg

(?<=...) podobnie jak w pierwszym przykładzie, tylko, że zadany wyraz w nawiasie musi się znajdować przed, np:

(?<=hello) world

(?<!...) Negacja powyższego przypadku. Czyli (?<!hello) world nie będzie pasować do "hello world", ale będzie dla np. "hell world".

Stosując powyższy zapis wyszukiwania, tekst w nawiasach nie będzie uwzględniony w wynikach. Ale, żeby tekst nie był uwzględniony w wynikach, można zastosować inny rodzaj zapisu:

\w(?:=)\d+ - wyrażenie będzie pasować dla np. w=52, z tym, że znak równa się znajduje się w nawiasie poprzedzony ?:. Właśnie to powoduje, ze znak ten nie będzie w wynikach.

Znak zapytania również jest wykorzystywany do ograniczenia zasięgu przeszukiwania dowolnych ciągów. Przykładowo mamy taki zapis:

"The scope of these option changes [zn]depends on[/zn] where in the [zn]pattern the[/zn] setting occurs."

I teraz chcemy wyłapać tekst miedzy znacznikami [zn] i [/zn]:

\[zn](.*)\[/zn]

Okaże się, że wcale nie jest to takie oczywiste. Algorytm wyrażeń wyłapie wszystko co się zaczyna od [zn] i kończy [/zn], czyli:

[zn]depends on[/zn] where in the [zn]pattern the[/zn]

Jeżeli natomiast dodamy znak zapytania, aby ograniczyć wyłapanie tekstu do pierwszego wystąpienia a nie ostatniego, tj:

\[zn](.*?)\[/zn]

Wynik:

[zn]depends on[/zn] where in the [zn]pattern the[/zn]

Oznacza to, że w tym przypadku znak zapytania posłużył do ograniczenia wyłapanego tekstu.
Zjawisko to określa się mianem jako wyrażenia zachłanne (greedy), a zastosowanie znaku zapytania eliminuje ten efekt.

Modyfikatory

Wyrażenia regularne typu PERL mają dodatkowo w swoim zastosowaniu pewne modyfikatory, które wprowadzają odpowiednią interpretacje wzorca lub jego części:

i – ignorowanie wielkości liter,
m - znaki początku i końca („^" i „$") będą odnosiły się do każdej nowej linii,
x - wszystkie znaki dowolnego odstępu (znaki białe) będą ignorowane i w ogóle nie brane pod uwagę,
s – oznacza, że metaznak kropka, oznaczający dowolny znak, pod uwagę też weźmie znak nowej linii (pierwotnie, bez modyfikatora nie uwzględnia tego znaku).

Modyfikatory stosujemy często dla całego wzorca i w zależności od programu, czy skryptu, który ma zaimplementowaną bibliotekę wyrażeń regularnych typu PERL, odpowiednio się je wprowadza. Przykładem może być język skryptowy PHP, w którym można wykorzystać funkcje preg_replace(), do zmiany ciągu danego wyrażenia pasującego do zadanego wzorca. Cały wzorzec jest pierwszym argumentem wspomnianej funkcji i musi być ograniczony w dowolne ogranicznik, który nie może wystąpić we wzorcu. Dość często wykorzystuje się znak slash'a „/". Np:

$tekst = preg_replace('@^https?://(www\.)?([^\.]+\..{2,5})$@', '\\2', $tekst);

W powyższym przykładzie wzorzec został ograniczony poprzez znak małpki „@". Dlatego, że stosując ogranicznik slash'a, zaburzy strukturę wzorca, ponieważ w nim już istnieją dwa znaki slash'a.
W przykładzie możemy dodatkowo dodać pewne modyfikatory, który na przykładzie funkcji preg_replace() dodaje się właśnie po ogranicznikach wzorca:

$tekst = preg_replace('@^https?://(www\.)?([^\.]+\..{2,5})$@si', '\\2', $tekst);

Zastosowano modyfikatory „s" i „i".

Modyfikatory można stosować do pewnego zakresu wzorca, aby działał lokalnie, ograniczony był do pewnego zakresu a nie globalnie. W tym celu stosuje się regułę wzorca:

(?imsx-imsx)

Zastosować regułę możemy na dwa sposoby:

pozycjonowanie (?i)stron(?-i) w internecie

Wzorzec będzie pasował do:
pozycjonowanie stron w internecie
oraz:
pozycjonowanie StRoN w internecie

ponieważ na słowo stron został zastosowany modyfikator „i", który ignoruje wielkość liter.

Drugim, krótszym sposobem zapisu jest:

pozycjonowanie (?i:stron) w internecie.

Wyrażenia regularne typu PERL

Informator internetowy - programowanie