Wbudowane w PHP mechanizmy korzystania ze wzorców wyrażeń regularnych są dość mało rozbudowane. Większość starych programistów woli korzystać ze standardów, które oferuje Perl. Od nie dawna taka możliwość istnieje także w PHP dzięki PCRE.
Jak zapewne wiesz, PHP posiada wbudowany mechanizm korzystania z wyrażeń regularnych. Zanim jednak powstał ten język większość webmasterów tworzyła swoje skrypty jako CGI. Nazwa ta nie wskazuje jednak na nazwę języka, w którym je tworzono. Głównie do tego celu wykorzystywano język C i Perl. Po wprowadzeniu PHP wielu programistom ciężko było się przestawić na nowy sposób operacji z wyrażeniami regularnymi. Dlatego też większość nadal pozostała przy korzystaniu ze starych metod, programując za pomocą C i Perla. Pozytywną dla rozwoju PHP rzeczą było pojawienie się w wersji 3.0.9 tego języka biblioteki PCRE (Perl Compaible Regular Expressions Library). Jest to zbiór funkcji umożliwiający przeprowadzanie dopasowywania wzorców przy użyciu wyrażeń regularnych zgodnych z Perlem. Dzięki tej bibliotece większość programstów korzystających z Perla przeżuciła się na bardziej wydajny PHP, a sam język stał się o wiele potężniejszym narzędziem. Jest jendak kilka wad. Okazało się, że sama biblioteka posiada pewne niezgodności z Perlem. Jeśli mamy w systemie zainstalowany Perl możemy obejść ograniczenia za pomocą funkcji exec(), wywołując za jej pomocą skrypt Perla którego zadaniem bęzie parsowanie odpowiednich danych. Więcej na temat tych ograniczeń przeczytasz w artykule „Niezgodności między PCRE a Perl”. Teraz przyjżyj się bliżej budowie wzorców zgodnych z Perlem.
Podobnie jak w większości języków to i tu wzorce tworzy się za pomocą zwykłych znaków i metaznaków. Metaznaki to specjalne znaki, które mają w sobie szczególne znaczenie. W Perlu znaki te to:
\ | ( ) [ { ^ $ * + ? . |
Jeśli chcemy aby podane znaki były traktowane dosłownie, a nie jako metaznaki, to musimy je poprzedzić lewym ukośnikiem. Musisz dobrze zapamiętać te znaki, gdyż później możesz przez przypadek napotkać na niespodziewane efekty. Oprócz metaznaków warto zapoznać się ze znakami specjalnymi. Dzięki nim możemy tworzyć skomplikowane wzorce, a ich składnia nadal pozostaje dla nas całkowicie zrozumiała. Spis wszystkich znaków specjalnych przedstawiam poniżej:
^ – początek wiersza $ – koniec wiersza . – dowolny znak, oprócz znaku nowego wiersza \077 – znak zapisany ósemkowo \A – początek tekstu \b – granica słowa \B – (nie) granica słowa \c – znak kontrolny \d – dowolna cyfra \D – dowolny znak, który nie jest cyfrą \f – nowa strona \n – znak nowego wiersza \r – powrót kursora \S – dowolny czarny znak \s – dowolny biały znak \t – tabulator \w – znak słowa (znaki alfanumeryczne i podkreślenie) \W – dowolny znak, który nie jest znakiem słowa \z – koniec tekstu \Z – koniec tekstu lub tuż przed końcowym znakiem nowego wiersza \x1 – znak zapisany szesnastkowo (#tekst) – komentarz. Całe takie wyrażenie jest pomijane (?:wzorzec) lub (?imsx-imsx:wzorzec) – grupy podwyrażeń działające jak 'i’, ale nie jest tworzone odwołanie (?=WYRAŻENIE) – pasuje tylko wtedy, gdy dalej pasuje WYRAŻENIE (?!WYRAŻENIE) – pasuje tylko wtedy, gdy dalej WYRAŻENIE nie pasuje (?<=WYRAŻENIE) – pasuje tylko, jeśli wcześniej dopasowano WYRAŻENIE (? (?(warunek)wzorzec1|wzorzec2) lub (?(warunek)wzorzec1) – wyrażenie regularne |
Skoro zapoznałeś sie już ze znakami specjalnymi, zajmę się teraz przedstawieniem podstawowych sposobów tworzenia wzorców. Każdy wzorzec musi zaczynać się znakiem prawego ukośnika i tak samo kończyć. Istnieje jeden wyjątek, ale o tym później. Tak więc wszystkie znaki specjalne i metaznaki działają tylko w strefie objętej przez dwa prawe ukośniki. Zanim przejdę do przedstawienia jakiegokolwiek przykładu postaram się jeszcze wyjaśnić Ci dodatkowe konstrukcje wykorzystwane we wzorcach. Pierwszym z nich będzie grupowanie znaków w klasy. Tworzy się ją za pomocą nawiasów kwadratowych. Zamieszczamy między nimi dowolne znaki i przy porównywaniu wzorca są dopasowywane każdy po kolei i ten, który pasuje jest brany pod uwagę. Ważne jest abyś zapamiętał, że brany jest pod uwagę tylko jeden znak, a nie cała klasa. Często wykorzystywany jest tu także znak ’-’ (kreski), który umożliwia podanie przedziału, np. zamiast pisać między nawiasami wszystkie litery alfabetu, możemy zapisać to tak: 'a-z’. W ten sposób unikamy tworzenia zbyt długich wzorców. Tak jak napisałem to wcześniej, cała klasa zanków odwołuje się tylko do jednego znaku z całej grupy. W ten sposób możemy znaleźć tylko jedne pasujący znak, ale co jeśli chcemy znaleźć całą grupę znaków tworzących słowo? Do tego celu posłuży nam znak '+’ (plus). Zastosować go należy dopiero po zamknięciu nawiasu kwadratowego, np. '[a-z]+’. Warto, żebyś wiedział co dokładnie oznacza ten znak, gdyż będziesz go wykorzystwał także w innych sytuacjach. Jego stosowanie oznacza, że poprzedni znak lub tak jak to było w przykładzie, poprzednia klasa znaków musi wystąpić conajmniej raz lub więcej. Dla zakończenia tematu klas dopowiem jeszcze, że istanieje coś takiego jak stworzenie klasy znaków, której znaki nie mogą pasować do wyrażenia. Do stworzenia takiej grupy stosuje się znak '^’, który trzeba umieścić na samym początku między nawiasami kwadratowymi, np. '[^a-z]+’ oznacza, że w podanym wyrażeniu nie może byż żadnych małych liter alfabetu.
Następną bardzo ważną rzeczą są nawiasy okrągłe, zwane 'operatorem grupowania’. Dzięki nim możemy kilkakrotnie odwoływać się do tego samego wzorca oszczedzając miejsce i czas. Dokładnie rzecz ujmując polega to na tym, że gdy stworzymy odpowiedni fragment wzorca i obejmiemy go w nawiasy okrągłe to później w tym samym wyrażeniu możemy się do niego odwołać jeszcze raz podając lewy ukośnik i cyfrę wzorca. Cyfra ta bierze się z kolejności wszystkich zainicjowanych między nawiasy grupowania wzorców w danym wyrażeniu, np.
/<(b)><(font)>.<\/\2><\/\1>/ |
Powyższy przykładowy wzorzec może wyglądać dość skomplikowanie, ale przedstawia prostą sytuację. Dotyczy on dopasowania wzorca do ciągu znaków przedstawiającego znaczniki HTML: <b> i <font>, a także ich zamknięcia </b> i </font>. Opisywany wcześniej sposób odwołania sie do już powstałej grupy za pomocą lewego ukośnika i cyfry grupy widocznie zmniejsza długość wzorca. Ten przykład pokazał tylko odrobine przydatności. Bardziej zrozumiesz działanie tego operatora w miare użytkownia z wzorców.
Koleinym wartym poruszenia tematem jest kotwiczenie wyrażenia za pomocą znaków '^’ i '$’. Ten pierwszy zdążyłeś już poznać, ale nie co w inny sposób. Jeśli zamieścimy go na samym początku wyrażenia oznacza on, że podany wzorzec musi być brany pod uwagę od początku ciągu znaków. Jeśli natomiast chcemy, aby podany wzorzec był brany pod uwagę na końcu ciągu to na samym końcu wzorca należy zamieścić znak '$’, np.
/^teskt$/ |
Podany wyżej wzorzec oznacz, że wyraz 'tekst’ musi się znajdować zarazem na początku i końcu ciągu znaków.
Po zapoznaniu się już z podstawami proponuje poruszyć temat operatorów alternatywy. Służą one do wyboru dopasowania wzorca. Aby użyć takiej alternatywy należy skorzystać ze znaku '|’ (pionowa kreska). Przyjęło się także, żeby wzorce alternatywne umieszczać w nawiasach okrągłych w celu uniknięcia włączenia przez przypadek znaków sąsiadujących ze wzorcami, a także, żeby było łatwo rozopznać początek i koniec alternatywy. Sprawdzenie wszystkich elementów alternatywy rozpoczyna się od lewej do prawej strony, a użyta zostaje pierwsza pasująca możliwość. Musisz jednak pamiętać, że próbując zastosować alternatywę w nawiasach kwadratowych zostanie ona potraktowana jako zwykły znak i nie da żadnego efektu.
Teraz pora na zapoznanie się z bardzo ważnymi we wzorcowaniu kwantyfikatorami wyrażeń regularnych. Są to określone znaki specjalne, które informują o liczbie wystąpień danego wzorca. Rozróżniamy następujące kwantyfikatory:
* – wystąpienie dowolną liczbę razy (od zera poczynając) + – wystąpienie co najmniej raz ? – wystąpienie raz lub wcale {n} – wystąpienie n razy {n,} – wystąpienie co najmniej n razy {,n} – wystąpienie nie więcej niż n razy {n,m} – wystąpienie co najmniej n razy, ale nie więcej niż m razy |
O znaku '+’ wposminałem już wcześniej i na pewno pamiętasz jego działanie. Na podstawie tamtego przykładu napewno zrozumiałeś już jego działanie, ale przypomne jeszcze raz sposób jego stosowania:
/a+/ |
Ten wzorzec oznacza, że litera 'a’ musi wystąpić conajmniej raz lub więcej. Prawda, że proste? Powiem jeszcze tylko, że stosowanie wszystkich wymienionych kwantyfikatorów odbywa się tak samo jak w podanym przykładzie, z tą tylko różnicą, że mają inne znaczenie. Wydaje mi się, że na podstawie opsiów łatwo zrozumieć ich działanie.
Przedostatni poruszany temat będzie dotyczył rozszerzenia wyrażeń regularnych, w których używa się nawiasów okrągłych ze znakiem zapytania. Są to swego rodzaju asercje, które wykorzystuje się do sprawdzania czy z przodu albo z tyłu znajduje się jakiś tekst, który nie ma należeć do dopasowania. Teraz przedstawie kilka prostych zastosowań:
/\w+(?=\s)/ |
Ten przykład sprawdza czy po znakach alfabetu występuje znak sterujący i jeśli tak to wzorzec pasuje.
/^\d{4}(?![a-z])$/ |
Z kolei ten przykład pasuje do wyrażenia, które składa się z czterech liczb na początku, a zaraz po nich sprawdza czy nie ma żadnych znaków alfabetu. Jeśli tak jest to wyrażenie pasuje do wzorca.
Wydaje mi się, że zroumiałeś już raczej działanie tych asercji, dlatego też przejde do ostatniego tematu w tym artykule. Będzie on dotyczył modyfikatorów wzorca. Są to znaki umieszczane wyjątkowo poza prawym ukośnikiem kończącym wzorzec. Na początek przedsawie wszystkie te modyfikatory:
i – pominięcie wielkości liter x – pominięcie białych znaków we wzorcu, dopuszczalne komentarze g – wszelkie możliwe operacje wykonywane są globalnie gc – mijesce wyszukiwania nie jest zerowane po niepowodzeniu dopasowania s – znak ’.’ pasuje także do znaku nowego wiersza m – znaki '^’ i '$’ mogą pasować także do włączonych znaków '\n’ o – wzorzec jest kompilowany tylko raz |
Myślę, że zrozumiałeś działanie tych modyfikatorów, a więc teraz przedstawię sposób ich używania na przykładzie:
/jAkiEs_HaSlO/i |
Zastosowanie tego modyfikatora sprawia, że podczas dopasowywania wzorca nie jest brana pod uwagę wielkość liter. Ma to słuszne zastosowanie, np. w momentach gdy wymagamy aby wzorzec był porównywany z małymi literami, ale wiemy, że przez przypadek mogą się tam znaleść duże litery.
Ponieważ przedstawiłem już chyba wszystkie możliwe informacje na temat wyrażeń regularnych w standardzie Perla to teraz zajmę się stworzeniem paru prostych przkładów. Najpierw jednak, aby skorzystać ze wzorców w PHP musimy zapoznać się z jedną z podstawowych funkcji, która nam do tego celu posłuży. Jest to funkcja preg_match(). Jej konstrukcja nie wydaje się być trudna, gdyż przypomina funkcje ereg(). Jako pierwszy argument podajemy wzorzec, a jako drugi ciąg znaków lub zmienną, która ma zostać porównana. Istnieje jeszcze trzeci argument, który posłuży nam za tablice, w której będą przechowywane pasujące do wzorca elementy. Pozniżej zamieszczam przykłady.
Załóżmy, że mamy tablice i chcemy spardzić, które elementu znajdujące się w niej pasują do naszego wzorca. Aby tego dokonać zapoznaj się z poniższym kodem:
<? // $tablica – tablica, w której są nasze dane $ile_pas = 0; while ($i < count($tablica)) { if (preg_match(„/^\w{4}$/i”)) { $ile_pas++; $i++; } else { $i++; } } print „Do wzorca pasuje $ile_pas elementów tablicy.”; ?> |
Dzięki powyższemu przykładowi możemy łatwo przeszukać naszą tablice i dopasować wzorcem odpowiednie elementy. A teraz zaprezentuje inny przykład. Wiemy, że w ciągu znaków znajduje się numer Gadu-Gadu i chcemy go rozpoznać. Przykład być może prosty, ale mogę tu pokazać przydatność kwantyfikatorów:
<? // $ciag – ciag znakow, w którym znajduje się wyszukiwany numerek GG preg_match(„/\d{4,7}/”, $ciag, $gg); ?> |
W tym przykładzie dzięki wzorcowi sprawdzam czy w wyrażeniu znajduje się numer składający się od czterech do siedmiu znaków i jeśli istnieje, jest zapisywany w tablicy '$gg’.
Myślę, że przekazałem Ci wszystkie podstawy tego jakże trudnego do opanowania tematu. Jeśli jednak poświęcisz się tworzeniem co raz to trudniejszych wzorców to dojdziesz do perfekcji i jak inni świetni programiści będziesz mógł chwalić się umiejętnością, która jest ceniona na wage złota.