Temat przeznaczony głównie dla programistów Perla, którym ciężko zrozumieć różnice między środowiskiem PCRE a Perlem. Porównuję tu podstawowe różnice, a także dodane elementy, których nie można było spotkać w oryginalnym standardzie Perla.
PCRE (Perl Compatible Regular Expressions Library) to biblioteka oferująca zbiór funkcji umożliwiających dopasowywanie wzorców przy użyciu wyrażeń regularnych zgodnych z Perlem. Posiada one jednak pewne niezgodności. W tym artykule postaram się Ci nieco przybliżyć te różnice.
Pierwszą z nich jest interpretacja znaków sterujących. Domyślnie są to wszystkie znaki rozpoznawane przez funkcję isspace() języka C, takie jak: znaki spacji, przesunięcia o jedną stronę, nowego wiersza, powrotu karetki, tabulacji poziomej i tabulacji pionowej. Istnieje jednak możliwość skompilowania PCRE z innymi tabelami typów znaków. Cały problem polega na tym, że w Perlu w wersji 5 wsród znaków sterujących nie ma znaku tabulacji pionowej. Znak ten przez długi czas był prze Perla rozpoznawany jako znak sterujący, mimo iż w dokumentacji uznawany był jako znak ucieczki. Tak było aż do wersji 5.002 Perla. W późniejzych wersjach nie jest on już zaliczany do wznaków sterujących.
Teraz załóżmy, że twój wzorzec składa się z podwzorców. PCRE podczas rozpoznawania ich zlicza je, ale ich pozycje w wektorze przesunięć nie są dodawane. Natomiast Perl ustawia ich wartości liczbowe na podstawie dowolnego pasującego wzorca, zanim dopasowanie deklaracji sie powiedzie. Dochodzi do tego jednak tylko w przypadku, gdy zanegowana deklaracja wyprzedzająca ma pojedynczą gałąź.
Nastęnym wartym zwrócenia uwagi tematem są znaki zer binarnych. Ich stosowanie w PCRE jest niedozwolone, gdyż są traktowane jako normalny łańcuch znaków. Aby obejść ten problem, jako reprezentacją zera binarnego należy się posłużyć znakiem ucieczki '\0′.
Poznieważ w Perlu część używanych znaków ucieczki jest wbudowana bezpośrednio w funkcje ogólnej obsługi łańcuchów znaków, to nie mogą one należeć do biblioteki PCRE. Dlatego też wyłączona je z obsługi. Do tych znaków należą: \l, \u, \L, \U, \E, \Q. To samo dotyczy deklaracji \G Perla, która nie jest ogólnie obsługiwana, a także zestawu wzorców (?{kod}). Je także wyłączono z oczywistych względów PCRE.
Piątą różnicą jaką możemy napotkać w bibliotece PCRE jest niezgodność związana z ustawieniami wychwyconych łańcuchów znaków, gdy powtarzała się część wzorca. Załóżmy, np. że chcemy dopasować wyrażenie 'aba’ do wzorca '/^(a(b)?)+$/’. Spowoduje ono, że ustawienie wartości zmiennej '$2′ przypadnie na 'b’. Jeśli natomiast w wyrażeniu 'aabbaa’ zastosujemy wzorzec '/^(aa(bb)?)$+/’ spowoduje to, że zmienna '$2′ zostanie nieustawiona. Gdyby podany wzorzec zmienić na '/^(aa(b(b))?)$+/’, to wartość 'b’ zostanie przypisana normalnie do zmiennych '$2′ i '$3′. Różnice te dotyczą wersji 5.005 Perla.
Jako ostatnią różnicę opisze elementy dodane do biblioteki PCRE, których nie można znaleźć w Perlu.
Perl w wersji 5.005 wymaga, aby wszystkie deklaracje wsteczne i alternatywne gałęzie deklaracji wstecznej były dopasowywane do łańcuchów znaków o stałej długości. W bibliotece PCRE ta zasada nieco się rozłamuje. Pozwala ona na stosowanie w przypadku alternatywnych gałęzi deklaracji wstecznej dopasowań do łańcuchów znaków o różnej długości. Niestety pozostałe przypadki pozostają podobnie jak w standardzie Perla.
Następnym wartym zwrócenia uwagi dodatkiem jest ustawienie PCRE_DOLLAR_ENDONLY. Jeśli go ustawimy, a PCRE_MULTILINE nie, to znak '$’ zostanie dopasowany tylko na końcu łańcucha znaków.
Podobnie jest w przypadku PCRE_EXTRA, przy którym po znaku lewego ukośnika należy zdefiniować klase znaków specjalnych. Prościej będzie to wytłumaczyć na przykładzie, a więc jeśli zapiszemy znak specjalny '\z’ to jest to nie poprawny zapis. Jeśli jednak zapiszemy tak: '\w ([a-zA-Z0-9_])’ to jest to jak najbardziej poprawne. Pamiętaj, że jeśli nie zdefiniujesz tej klasy to może to doprowadzić do błędu.
No i ostatnim dodatkiem jaki przedstawie jest ustawienie PCRE_UNGREEDY, za pomocą którego można ustawić rozszerzalność kwantyfikatorów powtórzeń. Domyślnie są one rozszerzalne, ale po zastosowaniu PCRE_UNREEDY nie.