Wyrażenia regularne (ang. regular expressions, w skrócie regex lub regexp) – wzorce, które opisują łańcuchy symboli. Teoria wyrażeń regularnych jest związana z teorią języków regularnych. Wyrażenia regularne mogą określać zbiór pasujących łańcuchów, mogą również wyszczególniać istotne części łańcucha.
Wyrażenia regularne to w informatyce teoretycznej ciągi znaków pozwalające opisywać języki regularne. W praktyce znalazły bardzo szerokie zastosowanie, pozwalają bowiem w łatwy sposób opisywać wzorce tekstu, natomiast istniejące algorytmy w efektywny sposób określają, czy podany ciąg znaków pasuje do wzorca lub wyszukują w tekście wystąpienia wzorca. Wyrażenia regularne w praktycznych zastosowaniach są zapisywane za pomocą bogatszej i łatwiejszej w użyciu składni niż ta stosowana w rozważaniach teoretycznych. Co więcej, opisane niżej powszechnie wykorzystywane wsteczne referencje (czyli użycie wcześniej dopasowanego fragmentu tekstu jako części wzorca), powodują, że wyrażenie regularne je zawierające może nie definiować języka regularnego.
Wyrażenia regularne stanowią integralną część narzędzi systemowych takich jak sed, grep, wielu edytorów tekstu, języków programowania przetwarzających tekst AWK i Perl, a także są dostępne jako odrębne biblioteki dla wszystkich języków używanych obecnie.
Dwie najpopularniejsze składnie wyrażeń regularnych to składnia uniksowa i składnia perlowa. Składnia perlowa jest znacznie bardziej rozbudowana. Jest ona używana nie tylko w języku Perl, ale także w innych językach programowania: Ruby, bibliotece PCRE do C i w narzędziu powłoki o nazwie pcregrep (znanego też jako pgrep). Perlową składnię stosuje się również w maskach przepisań mod rewrite.
Spis treści |
Wyrażeniem regularnym nad alfabetem
nazywamy ciąg znaków składający się z symboli
oraz symboli
z alfabetu
następującej postaci:
(słowo puste) są wyrażeniami regularnymi;
są wyrażeniami regularnymi;
są wyrażeniami regularnymi, to są nimi również:
(domknięcie Kleene'ego)
(konkatenacja)
(suma)
(grupowanie)Każde wyrażenie regularne definiuje pewien język formalny. Każdy język definiowany przez wyrażenie regularne jest regularny.
Język definiowany przez wyrażenie regularne jest definiowany indukcyjnie. Niech L(w) oznacza język definiowany przez w. Wtedy baza indukcji jest następująca:
(zbiór zawierający tylko słowo puste)
(zbiór pusty)
dla dowolnego a z alfabetuNatomiast do konstrukcji wyrażeń służą 3 symbole:
Gwiazdka wiąże najsilniej, konkatenacja słabiej, suma najsłabiej.
Wyrażenia są równoważne gdy definiują ten sam język: 

– suma jest przemienna
– łańcuch pusty jest elementem neutralnym konkatenacji
– suma jest łączna
– konkatenacja również jest łączna
– konkatenacja jest rozdzielna względem sumy

– domknięcie Kleene'ego jest idempotentne
Wyjaśnienie reguł:
– dowolny ciąg składający się
, np.
,
, a także pusty
– sekwencja, najpierw
, następnie 
– alternatywa, albo
, albo 
Wyrażenie
definiuje język zawierający dokładnie dwa słowa: "Wiki" i "wiki". To samo można wyrazić wprost
.
Wyrażenie
definiuje język wszystkich słów nad alfabetem
, które zawierają podsłowo baba.
Języki regularne można opisać również za pomocą automatów skończonych:
-przejściami (automat może zmienić swój stan bez podania symbolu wejściowego),
-przejść, orazJedne z pierwszych praktycznych implementacji wyrażeń regularnych opierały się właśnie na symulacji programowej automatu skończonego. Najpierw budowany jest NAS z
-przejściami zgodnie ze schematem pokazanym wyżej, następnie usuwane są
-przejścia, kolejnym krokiem jest determinizacja automatu skończonego, czego wynikiem jest otrzymanie DAS, ostatnim zaś etapem jego minimalizacja. Symulowanie DAS jest bardzo proste i szybkie; pierwsze narzędzia systemu Unix używały tej metody, wykorzystuje ją również język AWK, Tcl, a także biblioteki dla języka Haskell.
Na początku zostaną pokazane różnice i części wspólne zapisu teoretycznego i praktycznego.
| informatyka teoretyczna | praktyka | komentarz |
|---|---|---|
![]() |
brak | w praktyce zbioru pustego nie podaje się wprost |
, ![]() |
(, ) lub \(, \) | w niektórych implementacjach symbole specjalne poprzedza się backslashem |
![]() |
| lub \| | j.w. |
![]() |
[0123abcdefgh] lub krócej [0-3a-h] | zakres znaków (dokładny opis – patrz niżej) |
![]() |
. | dowolny znak z alfabetu (tutaj małe i duże litery, w praktyce cały zestaw znaków); w teoretycznym zapisie wymaga wyliczenia wszystkich znaków z alfabetu |
![]() |
* lub \* | 0 lub więcej wystąpień |
![]() |
e? | wyrażenie e występuje 0 lub 1 raz |
![]() |
e+ | wyrażenie e występuje 1 lub więcej razy |
| brak | ^ | metaznak oznaczający początek łańcucha (lub początek wiersza, jeśli przetwarzane są wielowierszowe napisy); w teoretycznych rozważaniach dopasowuje się całe słowa, podczas gdy w praktyce zwykle celem jest znalezienie dopasowania wewnątrz dłuższego tekstu, dlatego dopasowanie do całości wymaga dodatkowych oznaczeń
w zapisie [^e] oznacza negację e |
| brak | $ | metaznak oznaczający koniec łańcucha |
![]() |
e{4} | określona liczba powtórzeń (tutaj 4); rozszerzenie Perla |
![]() |
e{4,7} | określony zakres liczby powtórzeń wyrażenia e (tutaj od 4 do 7); rozszerzenie Perla |
Podstawowe elementy wyrażeń regularnych:
Polski kod pocztowy składa się z sekwencji następujących elementów:
Ostatecznie wyrażenie regularne, które opisuje kod pocztowy [0-9][0-9]-[0-9][0-9][0-9] lub wykorzystując opisane niżej rozszerzenia perla: [0-9]{2}-[0-9]{3}.
Napis reprezentujący liczbę rzeczywistą składa się z następujących elementów:
Wyrażenie regularne opisujące taki napis: [+-]?[0-9]+(\.[0-9]+)?.
Wyrażenie sprawdzające poprawność adresów poczty elektronicznej (w wersji uproszczonej, opisujące adresy w najpopularniejszej formie): ^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.([a-zA-Z]{2,}){1}$.
Rozszerzenia Perla to między innymi:
Kwantyfikatory w wyrażeniach regularnych dopasowują tak wiele znaków jak to możliwe, są to więc tzw. wyrażenia zachłanne (greedy – z ang. zachłanne, łapczywe). Może to być znaczącym problemem. Przykładowo, aby dopasować pierwszy element, znajdujący się w podwójnych nawiasach kwadratowych w tekście:
użytkownik użyłby najchętniej wyrażenia (\[\[.*\]\]), które wygląda poprawnie (nawias kwadratowy powinien być interpretowany jako znak, dlatego poprzedzony jest odwrotnym ukośnikiem), jednak zwróci ciąg [[Tajwan]]ie, [[26 stycznia]] [[1990]] zamiast oczekiwanego [[Tajwan]].
Są dwie metody na uniknięcie tego problemu. Po pierwsze, zamiast określać co powinno być dopasowane, można określić co nie powinno być dopasowane. W tym przypadku ] jest znakiem niepożądanym, więc wyrażenie miałoby postać (\[\[[^\]]*\]\]). Jednak nie uda się w ten sposób dopasować ciągu znaków w postaci:
Drugą, bardziej współczesną metodą jest "zmuszenie" kwantyfikatora, aby nie był typu "greedy", poprzez dopisanie za nim znaku zapytania (\[\[.*?\]\]). Są to tak zwane "leniwe" (ang. lazy) odmiany kwantyfikatorów.