Wyrażenia regularne kompatybilne z Perlem

Wyrażenia regularne kompatybilne z Perlem
Oryginalni autorzy Filip Hazel
Wersja stabilna
PCRE1 8.45 / 15 czerwca 2021 ; 20 miesięcy temu ( 2021-06-15 )
PCRE2 10.40 / 15 kwietnia 2022 ; 10 miesięcy temu ( 2022-04-15 )
Magazyn
Napisane w C
System operacyjny Międzyplatformowe
Typ Biblioteka dopasowywania wzorców
Licencja BSD
Strona internetowa pcre .org Edit this at Wikidata

Perl Compatible Regular Expressions ( PCRE ) to biblioteka napisana w C , która implementuje silnik wyrażeń regularnych , inspirowany możliwościami języka programowania Perl . Philip Hazel zaczął pisać PCRE latem 1997 roku. Składnia PCRE jest znacznie potężniejsza i bardziej elastyczna niż którykolwiek ze smaków wyrażeń regularnych POSIX (BRE, ERE) i niż wiele innych bibliotek wyrażeń regularnych.

Chociaż PCRE pierwotnie miał na celu równoważność funkcji z Perlem, te dwie implementacje nie są w pełni równoważne. W fazie PCRE 7.x i Perl 5.9.x oba projekty koordynowały rozwój, a funkcje były przenoszone między nimi w obu kierunkach.

W 2015 roku wydano rozwidlenie PCRE ze zmienionym interfejsem programowania (API). Oryginalne oprogramowanie, teraz nazywane PCRE1 (seria 1.xx – 8.xx), ma naprawione błędy, ale nie jest dalej rozwijane. Od 2020 roku jest uważany za przestarzały, a obecna wersja 8.45 prawdopodobnie będzie ostatnią. Nowy kod PCRE2 (seria 10.xx) miał wiele rozszerzeń i ulepszeń kodowania i jest miejscem, w którym odbywa się rozwój.

Wiele znanych programów typu open source , takich jak serwery HTTP Apache i Nginx oraz języki skryptowe PHP i R , zawiera bibliotekę PCRE; zastrzeżone oprogramowanie może robić to samo, ponieważ biblioteka jest na licencji BSD. Począwszy od Perla 5.10, PCRE jest również dostępny jako zamiennik domyślnego silnika wyrażeń regularnych Perla poprzez re::engine::PCRE .

Bibliotekę można zbudować w systemie Unix, Windows i kilku innych środowiskach. PCRE2 jest rozprowadzany z opakowaniem POSIX C, kilkoma programami testowymi i programem narzędziowym pcre2grep , który jest wbudowany w tandem z biblioteką.

Cechy

Obsługa kompilatora just-in-time

Ta opcjonalna funkcja jest dostępna, jeśli jest włączona podczas tworzenia biblioteki PCRE2. Duże korzyści w zakresie wydajności są możliwe, gdy (na przykład) program wywołujący wykorzystuje funkcję z kompatybilnymi wzorcami, które są wykonywane wielokrotnie. Obsługa kompilatora just-in-time została napisana przez Zoltana Herczega i nie jest uwzględniona w opakowaniu POSIX.

Elastyczne zarządzanie pamięcią

Wykorzystanie stosu systemowego do backtrackingu może być problematyczne w PCRE1, dlatego ta cecha implementacji została zmieniona w PCRE2. Stos jest teraz używany do tego celu, a łączna kwota może być ograniczona. Problem przepełnienia stosu , który pojawiał się regularnie w PCRE1, nie występuje już w PCRE2 od wersji 10.30 (2017).

Konsekwentne zasady ucieczki

Podobnie jak Perl, PCRE2 ma spójne reguły ucieczki: każdy znak inny niż alfanumeryczny może zostać zastąpiony jego dosłowną wartością przez poprzedzenie znaku \ (ukośnikiem odwrotnym). Każdy znak alfanumeryczny poprzedzony ukośnikiem odwrotnym zwykle nadaje mu specjalne znaczenie. W przypadku, gdy sekwencja nie została zdefiniowana jako specjalna, wystąpi błąd. Różni się to od Perla, który zgłasza błąd tylko wtedy, gdy jest w trybie ostrzegawczym (PCRE2 nie ma trybu ostrzegawczego). W podstawowych wyrażeniach regularnych POSIX czasami ukośniki odwrotne omijały znaki inne niż alfanumeryczne (np. \. ), a czasami wprowadzały specjalną cechę (np. \(\) ).

Rozszerzone klasy postaci

Oprócz dłuższych nazw POSIX obsługiwane są jednoliterowe klasy znaków . Na przykład \d dopasowuje dowolną cyfrę dokładnie tak, jak [[:cyfra:]] w wyrażeniach regularnych POSIX.

Minimalne dopasowanie (inaczej „niechciwy”)

A ? można umieścić po dowolnym kwantyfikatorze powtórzeń, aby wskazać, że należy użyć najkrótszego dopasowania. Domyślnie najpierw próbuje się znaleźć najdłuższe dopasowanie , a następnie przechodzimy przez krótsze dopasowania: np. a.*?b pasowałoby do pierwszego "ab" w "ababab", gdzie a.*b pasowałoby do całego łańcucha.

Jeśli ustawiona jest flaga U , to kwantyfikatory są domyślnie niechciwe (leniwe), podczas gdy ? czyni ich chciwymi.

Właściwości znaków Unicode

Unicode definiuje kilka właściwości dla każdego znaku. Wzorce w PCRE2 mogą pasować do tych właściwości: np. \ p { Ps } .*? \ p { Pe } pasowałoby do łańcucha rozpoczynającego się od dowolnego „otwierającego znaku interpunkcyjnego” i kończącego się dowolnym „znakiem interpunkcyjnym zamkniętym”, takim jak [abc] . Dopasowywanie pewnych „normalnych” metaznaków może być sterowane przez właściwości Unicode, gdy ustawiona jest opcja kompilacji PCRE2_UCP. Opcję można ustawić dla wzorca, włączając (*UCP) na początku wzoru. Opcja zmienia zachowanie następujących metaznaków: \B , \b , \D , \d , \S , \s , \W , \w , oraz niektórych klas znaków POSIX. Na przykład zestaw znaków dopasowanych przez \w (znaki słowa) jest rozszerzony o litery i litery akcentowane zgodnie z definicją właściwości Unicode. Takie dopasowanie jest wolniejsze niż normalne ( ASCII -tylko) alternatywa inna niż UCP. Zauważ, że opcja UCP wymaga, aby biblioteka została zbudowana tak, aby zawierała obsługę Unicode (jest to ustawienie domyślne dla PCRE2). Bardzo wczesne wersje PCRE1 obsługiwały tylko kod ASCII. Później dodano obsługę UTF-8. Obsługa UTF-16 została dodana w wersji 8.30, a obsługa UTF-32 w wersji 8.32. PCRE2 zawsze obsługiwał wszystkie trzy kodowania UTF.

Dopasowywanie wielowierszowe

^ i $ mogą pasować tylko na początku i na końcu łańcucha lub na początku i na końcu każdej „linii” w ciągu, w zależności od ustawionych opcji.

Opcje nowej linii/podziału linii

Podczas kompilacji PCRE wybierana jest domyślna wartość nowego wiersza. To, która nowa linia/podział linii jest w efekcie, wpływa na to, gdzie PCRE wykrywa początki linii ^ i końce linii $ (w trybie wielowierszowym), jak również to, co pasuje do kropki (niezależnie od trybu wielowierszowego, chyba że ustawiono opcję dotall (?s) ). Wpływa to również na procedurę dopasowywania PCRE (od wersji 7.0): gdy niezakotwiczony wzorzec nie pasuje na początku sekwencji nowej linii, PCRE przechodzi przez całą sekwencję nowej linii przed ponowną próbą dopasowania. Jeśli alternatywna opcja nowej linii zawiera CRLF jako jeden z prawidłowych podziałów wierszy, nie pomija znaku \n w CRLF, jeśli wzorzec zawiera określone odwołania \r lub \n (od wersji 7.3). Od wersji 8.10 metaznak \N zawsze pasuje do dowolnego znaku innego niż znaki końca wiersza. Ma takie samo zachowanie jak . gdy opcja dotall aka (?s) nie działa.

Opcję nowej linii można zmienić za pomocą opcji zewnętrznych podczas kompilacji PCRE i podczas jej uruchamiania. Niektóre aplikacje korzystające z PCRE zapewniają użytkownikom możliwość zastosowania tego ustawienia za pomocą opcji zewnętrznej. Tak więc opcję nowej linii można również podać na początku wzorca, używając jednego z poniższych:

  • (*LF) Nowa linia to znak nowego wiersza. Odpowiednie podziały linii można dopasować za pomocą \n .
  • (*CR) Nowa linia to znak powrotu karetki. Odpowiednie podziały wierszy można dopasować za pomocą \r .
  • (*CRLF) Nowa linia/podział wiersza to znak powrotu karetki, po którym następuje wysunięcie wiersza. Odpowiednie podziały wierszy można dopasować za pomocą \r\n .
  • (*ANYCRLF) Każde z powyższych zdarzeń napotkanych w danych spowoduje wyzwolenie przetwarzania nowego wiersza. Odpowiednie podziały wierszy można dopasować za pomocą (?: \ r \ n ?| \ n ) lub za pomocą \R . Zobacz poniżej konfigurację i opcje dotyczące dopasowania odwrotnego ukośnika-R.
  • (*ANY) Dowolny z powyższych plus specjalne podziały linii Unicode.

Gdy nie jest to tryb UTF-8, odpowiednie podziały wierszy można dopasować za pomocą (?: \ r \ n ?| \ n | \ x0B | \ f | \ x85 ) lub \R .

W trybie UTF-8 dwa dodatkowe znaki są rozpoznawane jako podziały linii za pomocą (*ANY) :

  • LS (separator linii, U+2028),
  • PS (separator akapitu, U+2029).

W systemie Windows, w danych innych niż Unicode, niektóre znaki końca linii DOWOLNE mają inne znaczenie.

Na przykład \x85 może pasować do wielokropka poziomego, a jeśli zostanie napotkany podczas działania DOWOLNEGO nowego wiersza, uruchomi przetwarzanie nowego wiersza.

Zobacz poniżej konfigurację i opcje dotyczące dopasowania odwrotnego ukośnika-R.

Opcje odwrotnego ukośnika-R

Podczas kompilacji PCRE wybierana jest wartość domyślna pasująca do \R . Wartością domyślną może być dopasowanie końca wiersza odpowiadającego ANYCRLF lub odpowiadającego ANY. W razie potrzeby wartość domyślną można przesłonić, umieszczając (*BSR_UNICODE) lub (*BSR_ANYCRLF) na początku wzorca. Podając (*BSR..) , możesz również podać opcję (* nowa linia ) , np. (*BSR_UNICODE)(*ANY) reszta wzorca . Opcje odwrotnego ukośnika-R mogą być również zmieniane za pomocą opcji zewnętrznych przez aplikację wywołującą PCRE2 podczas kompilacji wzorca.

Początek opcji wzoru

Opcje podziału linii, takie jak (*LF) udokumentowane powyżej; opcje odwrotnego ukośnika-R, takie jak (*BSR_ANYCRLF) udokumentowane powyżej; Opcja właściwości znaków Unicode (*UCP) udokumentowana powyżej; (*UTF8) udokumentowana w następujący sposób: jeśli twoja biblioteka PCRE2 została skompilowana z obsługą UTF , możesz określić opcję (*UTF) na początku wzorca zamiast ustawiania opcji zewnętrznej, aby wywołać tryb UTF-8, UTF-16 lub UTF-32.

Odwołania wsteczne

Wzór może odnosić się do wyników poprzedniego dopasowania. Na przykład (a|b)c\1 pasowałoby do „aca” lub „bcb” i nie pasowałoby na przykład do „acb”.

Nazwane podwzorce

Podwzorzec (otoczony nawiasami okrągłymi, jak (...) ) może być nazwany poprzez włączenie wiodącego ?P<nazwa> po nawiasie otwierającym. Nazwane wzorce podrzędne to funkcja, którą PCRE przejęło z wyrażeń regularnych Pythona .

Ta cecha została następnie przyjęta przez Perla, więc teraz nazwane grupy mogą być również definiowane przy użyciu (?<name>...) lub (?'name'...) , jak również (?P<name>...) . Do nazwanych grup można odwoływać się wstecz, na przykład: (?P=nazwa) (składnia Pythona) lub \k'name' (składnia Perla).

podprogramy

Podczas gdy odwołanie wsteczne zapewnia mechanizm odnoszący się do tej części podmiotu, która wcześniej pasowała do podwzorca, podprogram zapewnia mechanizm ponownego wykorzystania wcześniej zdefiniowanego podwzorca. Opcje wzorca podrzędnego, takie jak niezależność wielkości liter, są ustalane podczas definiowania wzorca podrzędnego. (ac)(?1) pasuje do „aacabc” lub „abcadc”, podczas gdy użycie odwołania wstecznego (ac)\1 nie pasuje, chociaż oba pasują do „aacaac” lub „abcabc”. PCRE obsługuje również konstrukcję Oniguruma inną niż Perl dla podprogramów. Są one określone za pomocą \g<subpat-number> lub \g<nazwa-subpat> .

Grupowanie atomowe

Grupowanie atomowe to sposób na zapobieganie cofaniu się we wzorcu. Na przykład a++bc dopasuje jak najwięcej „a” i nigdy nie wykona kopii zapasowej, aby spróbować o jeden mniej.

Twierdzenia wsteczne i wsteczne

Twierdzenie Spojrzeć za siebie Patrz przed siebie
Pozytywny (? <= wzór ) (? = wzór )
Negatywny (? <! wzór ) (? ! wzór )

Asercje wsteczne i wyprzedzające w wyrażeniach regularnych Perla

Wzorce mogą potwierdzać, że poprzedni lub kolejny tekst zawiera wzorzec bez konsumowania dopasowanego tekstu (twierdzenie o zerowej szerokości). Na przykład / \w+(?=\t) / dopasowuje słowo, po którym następuje tabulator , bez dołączania samej tabulatora.

Asercje wsteczne nie mogą mieć niepewnej długości, chociaż (w przeciwieństwie do Perla) każda gałąź może mieć inną stałą długość.

\K można użyć we wzorcu, aby zresetować początek bieżącego całego meczu. Zapewnia to elastyczne alternatywne podejście do asercji wstecznych, ponieważ odrzucona część dopasowania (część poprzedzająca \K ) nie musi mieć ustalonej długości.

Sekwencje specjalne dla asercji o zerowej szerokości

Np. \b dla dopasowania "granic słów" o zerowej szerokości, podobnie do (? < = \ W )(?= \ w )|(? < = \ w )(?= \ W )|^|$ .

Uwagi

Komentarz zaczyna się od (?# i kończy się na następnym nawiasie zamykającym.

Wzorce rekurencyjne

Wzorzec może odnosić się rekurencyjnie do samego siebie lub do dowolnego podwzorca. Na przykład wzorzec \ (( a *|(? R ))* \ ) będzie pasował do dowolnej kombinacji zrównoważonych nawiasów i „a”.

Ogólne objaśnienia

Wyrażenia PCRE mogą być osadzone (?C n ) , gdzie n jest pewną liczbą. Spowoduje to wywołanie zewnętrznej funkcji zdefiniowanej przez użytkownika za pośrednictwem interfejsu API PCRE i może zostać użyte do osadzenia dowolnego kodu we wzorcu.

Różnice w stosunku do Perla

Różnice między PCRE2 i Perlem (od wersji Perl 5.9.4) obejmują między innymi:

Do wydania 10.30 dopasowania rekurencyjne były atomowe w PCRE i nieatomowe w Perlu

Oznaczało to, że "<<!>!>!>><>>!>!>!>" =~ /^(<(?:[^<>]+|(?3)|(?1))* >)()(!>!>!>)$/ pasowałoby w Perlu, ale nie w PCRE2 do wydania 10.30.

Wartość bufora przechwytywania pochodzącego z ? kwantyfikator (dopasowanie 1 lub 0 razy), gdy jest zagnieżdżony w innym kwantyfikowanym buforze przechwytywania, jest inny

W Perlu "aba" =~ /^(a(b)?)+$/ ; spowoduje, że 1 $ będzie zawierać „a”, a 2 $ będzie zawierało undef , ale w PCRE spowoduje, że 2 $ będzie zawierało „b”.

PCRE umożliwia nadawanie nazwanym buforom przechwytywania nazw numerycznych; Perl wymaga, aby nazwa była zgodna z zasadą gołych słów

Oznacza to, że \g{} jest jednoznaczne w Perlu, ale potencjalnie niejednoznaczne w PCRE.

Nie jest to już różnica od czasu PCRE 8.34 (wydanego 15.12.2013), która nie pozwala już zaczynać nazw grup od cyfry.

PCRE pozwala, aby alternatywy w obrębie lookbehind miały różną długość

W asercjach wstecznych zarówno PCRE, jak i Perl wymagają wzorców o stałej długości.

Oznacza to, że zarówno PCRE, jak i Perl nie zezwalają na wzorce o zmiennej długości używające kwantyfikatorów w asercjach wstecznych.

Jednak Perl wymaga, aby wszystkie alternatywne gałęzie asercji wstecznej miały taką samą długość, podczas gdy PCRE pozwala, aby te alternatywne gałęzie miały różną długość od siebie, o ile każda gałąź nadal ma stałą długość.

PCRE nie obsługuje pewnych „eksperymentalnych” konstrukcji Perla

Takie jak (??{...}) (wywołanie zwrotne, którego zwrot jest oceniany jako część wzorca) ani konstrukcja (?{}) , chociaż ta ostatnia może być emulowana przy użyciu (?Cn) .

Zlecenia sterujące rekursją dodane w serii Perl 5.9.x również nie są obsługiwane.

Obsługa eksperymentalnych czasowników sterujących cofaniem (dodana w Perlu 5.10) jest dostępna w PCRE od wersji 7.3.

Są to (*FAIL) , (*F) , (*PRUNE) , (*SKIP) , (*THEN) , (*COMMIT) i (*ACCEPT) .

Odpowiednie użycie argumentów przez Perla z czasownikami sterującymi cofania nie jest generalnie obsługiwane.

Należy jednak zauważyć, że od wersji 8.10 PCRE obsługuje następujące czasowniki z określonym argumentem: (*MARK:markName) , (*SKIP:markName) , (*PRUNE:markName) i (*THEN:markName) .

Od wersji 10.32 PCRE2 obsługuje (*ACCEPT:markName) , (*FAIL:markName) i (*COMMIT:markName) .

PCRE i Perl różnią się nieco pod względem tolerancji błędnych konstrukcji

Perl dopuszcza kwantyfikatory na konstrukcji (?!...) , co jest bezsensowne, ale nieszkodliwe (choć nieefektywne); PCRE generuje błąd w wersjach wcześniejszych niż 8.13.

PCRE ma twarde ograniczenie głębokości rekurencji, Perl nie

Z domyślnymi opcjami kompilacji "bbbbXcXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" =~ /.X(.+)+X/ nie będzie pasować ze względu na limit, ale Perl dopasuje to poprawnie.

Perl używa sterty do rekurencji i nie ma sztywnego limitu głębokości rekurencji, podczas gdy PCRE2 ma domyślny limit czasu kompilacji, który może być dostosowywany w górę lub w dół przez aplikację wywołującą.

Weryfikacja

Z wyjątkiem powyższych punktów, PCRE jest w stanie przejść testy w pliku Perla „ t/op/re_tests ”, jednym z głównych testów regresji na poziomie składni dla silnika wyrażeń regularnych Perla.

Uwagi i odniesienia

Notatki

  1. ^ Podstawowa biblioteka PCRE2 zapewnia zarówno funkcję dopasowywania, jak i dopasowywania i zastępowania.
  2. ^

    Czy część \ x85 nie jest \ xC2 \ x85 ? (tj. (?: \ r \ n ?| \ n | \ x0B | \ f | \ xC2 \ x85 ) , jako U+0085 != 0x85) Zastrzeżenie : Jeśli wzorzec \ xC2 \ x85 nie zadziałało: poeksperymentuj z ustawieniami Unicode implementacji RegEx lub spróbuj zastąpić je następującymi:
    • \ x { 0085 }
    • \ u0085

Bibliografia

  1. ^ Ostateczna wersja PCRE1: https://lists.exim.org/lurker/message/20210615.162400.c16ff8a3.en.html
  2. ^ Wydania: https://github.com/PCRE2Project/pcre2/releases
  3. ^ Exim i PCRE: Jak wolne oprogramowanie zawładnęło moim życiem (1999-12), Philip Hazel , s. 7: https://www.ukuug.org/events/winter99/proc/PH.ps

    A co z PCRE?

    • Napisane latem 1997, umieszczone na serwerze ftp.
    • Ludzie to znaleźli i założyli listę mailingową.
    • Pojawiła się strużka ulepszeń.
  4. ^
  5. ^ PCRE2 - Wyrażenia regularne zgodne z Perlem (poprawione API) (2020), University of Cambridge : https://pcre.org/pcre2.txt
  6. ^ Różnice między PCRE2 a Perlem (13.07.2019), Philip Hazel : https://www.pcre.org/current/doc/html/pcre2compat.html
  7. ^ Cytuj dziennik zmian PCRE ( https://www.pcre.org/original/changelog.txt ): „Perl nie pozwala już, aby nazwy grup zaczynały się od cyfr, więc wprowadziłem tę zmianę również w PCRE”.
  8. ^ Dziennik zmian dla PCRE2: https://www.pcre.org/changelog.txt

Zobacz też

Linki zewnętrzne