Gdy trzeba sprawdzić format adresu e-mail, wyciągnąć numer zamówienia z długiego tekstu albo zweryfikować dane w teście automatycznym, zwykłe wyszukiwanie znak po znaku szybko przestaje wystarczać. Właśnie wtedy przydają się wyrażenia regularne, czyli regexy. Poniżej pokazuję, jak działają, z jakich elementów się składają, gdzie pomagają w automatyzacji testów i dlaczego nie zawsze są najlepszym narzędziem.
Regex zamienia opis wzorca tekstowego w praktyczne reguły wyszukiwania
- Regex to wzorzec opisujący, jaki tekst ma pasować do określonej reguły.
- Można go używać do wyszukiwania, walidacji, wyciągania i zamiany fragmentów tekstu.
- W testach automatycznych sprawdza między innymi format danych i zawartość komunikatów.
- Najważniejsze elementy składni to klasy znaków, kwantyfikatory, kotwice, grupy i alternatywy.
- Regex nie rozumie znaczenia tekstu, a jego składnia może się różnić zależnie od języka i silnika.

Regex to wzorzec, a nie zwykły ciąg znaków
Regex, od angielskiego regular expression, jest instrukcją opisującą, jak powinien wyglądać szukany tekst. Nie wskazuje wyłącznie konkretnego słowa. Może określać na przykład, że tekst ma zaczynać się od dwóch liter, zawierać pięć cyfr i kończyć się określonym sufiksem.
Prosty wzorzec kot znajdzie dokładnie taki ciąg znaków. Z kolei k.t dopasuje między innymi „kot”, „kat” i „kit”, ponieważ kropka oznacza dowolny pojedynczy znak. To właśnie odróżnia wyrażenie regularne od klasycznego wyszukiwania tekstu.
W praktyce regex może pełnić cztery różne funkcje:
- wyszukiwanie określonego fragmentu w większym tekście,
- walidacja, czyli sprawdzenie, czy dane mają właściwy format,
- ekstrakcja informacji, na przykład numeru faktury z komunikatu,
- zamiana znalezionych fragmentów na inny tekst.
Ważne rozróżnienie polega na tym, że regex sprawdza głównie strukturę danych, a nie ich prawdziwość. Wzorzec może potwierdzić, że tekst przypomina adres e-mail, ale nie sprawdzi, czy skrzynka rzeczywiście istnieje. W automatyzacji testów takie rozdzielenie ma duże znaczenie.
Jak czytać podstawową składnię wyrażeń regularnych
Na początku symbole wyglądają jak przypadkowy ciąg znaków, ale większość wzorców opiera się na kilku powtarzalnych elementach. Ja zwykle czytam regex od lewej do prawej, rozbijając go na małe reguły zamiast próbować zapamiętać całość naraz.
| Element | Znaczenie | Przykład |
|---|---|---|
. |
Dowolny pojedynczy znak | k.t |
\d |
Cyfra, zwykle od 0 do 9 | \d{4} |
\s |
Biały znak, na przykład spacja lub tabulator | \s+ |
[abc] |
Jeden znak z podanego zbioru | [abc] |
[^abc] |
Jeden znak spoza podanego zbioru | [^0-9] |
+ |
Co najmniej jedno wystąpienie | \d+ |
* |
Zero lub więcej wystąpień | \s* |
? |
Zero lub jedno wystąpienie | -? |
{n} |
Dokładnie n wystąpień | \d{5} |
{n,m} |
Od n do m wystąpień | \d{2,4} |
^ i $
|
Początek i koniec tekstu | ^\d{5}$ |
| |
Alternatywa, czyli „lub” | kot|pies |
Wzorzec ^\d{2}-\d{3}$ pasuje do prostego zapisu kodu pocztowego, na przykład 12-345. Znaki ^ i $ są tu bardzo ważne, ponieważ wymagają dopasowania całego tekstu, a nie tylko jego fragmentu.
Grupy i przechwytywanie danych
Nawiasy okrągłe pozwalają grupować elementy. Wzorzec (\d{4})-(\d{2})-(\d{2}) może znaleźć datę w formacie rok-miesiąc-dzień, a poszczególne grupy pozwalają później odczytać rok, miesiąc i dzień osobno.
Jeżeli grupowanie nie ma służyć przechwytywaniu, można użyć składni (?:...). To drobny szczegół, ale w większych wzorcach pomaga ograniczyć liczbę niepotrzebnych wyników i poprawia czytelność kodu.
Znaki specjalne wymagają ucieczki
Niektóre symbole mają w regexie specjalne znaczenie. Kropka oznacza dowolny znak, więc aby wyszukać prawdziwą kropkę, trzeba zapisać ją jako \.. Podobnie zapis \? oznacza dosłowny znak zapytania.
To jeden z błędów, które widuję najczęściej. Autor chce znaleźć adres internetowy lub nazwę pliku, ale zapomina, że kropka w regexie nie jest zwykłą kropką. W efekcie wzorzec dopasowuje więcej danych, niż powinien.
Jak regex wspiera automatyzację testów
W automatyzacji testów wyrażenia regularne są przydatne wszędzie tam, gdzie wynik może się zmieniać, ale jego format pozostaje przewidywalny. Test nie musi wtedy oczekiwać jednej sztywnej wartości. Może sprawdzić, czy odpowiedź spełnia określoną regułę.
Sprawdzanie komunikatów i identyfikatorów
Załóżmy, że aplikacja wyświetla komunikat Zamówienie #A83921 zostało utworzone. Zamiast porównywać cały tekst znak po znaku, można sprawdzić wzorzec Zamówienie #[A-Z]\d{5} zostało utworzone.
Takie podejście jest odporne na zmianę konkretnego numeru zamówienia, ale nadal wykryje błędny format identyfikatora. To dobry przykład testu, który sprawdza regułę biznesową, a nie przypadkową wartość wygenerowaną podczas jednego uruchomienia.
Walidowanie danych wejściowych
Regex może pomóc sprawdzić, czy pole zawiera numer telefonu, kod pocztowy, identyfikator klienta albo datę. Przykładowy wzorzec dla polskiego kodu pocztowego wygląda tak:
^\d{2}-\d{3}$
W teście warto sprawdzić zarówno przypadki poprawne, jak i błędne. Dla powyższej reguły będą to między innymi 00-950, 12-345, 12345 oraz 12 345. Ostatnie dwa przykłady powinny zostać odrzucone, jeśli aplikacja wymaga zapisu z łącznikiem.
Analizowanie odpowiedzi API i logów
W testach integracyjnych regex może wyciągać token, identyfikator lub numer wersji z odpowiedzi tekstowej. Trzeba jednak uważać, aby nie zastępować nim parsera JSON, XML czy HTML. Jeśli dane mają formalną strukturę, dedykowany parser jest bezpieczniejszy i czytelniejszy.
Regex sprawdza się natomiast przy logach, których format jest prosty i powtarzalny. Wzorzec status=(\d{3}) pozwoli znaleźć kod odpowiedzi HTTP, a grupa przechwytująca umożliwi późniejsze porównanie go z oczekiwaną wartością.
Przykład w Pythonie
W Pythonie do pracy z wyrażeniami regularnymi służy moduł re. Prosty test może wyglądać tak:
import re
komunikat = "Zamówienie #A83921 zostało utworzone"
wzorzec = r"Zamówienie #[A-Z]\d{5} zostało utworzone"
assert re.fullmatch(wzorzec, komunikat)
Użycie fullmatch jasno komunikuje, że cały tekst ma pasować do wzorca. To bezpieczniejsze niż ogólne wyszukiwanie, które mogłoby uznać test za zaliczony tylko dlatego, że poprawny fragment znalazł się w środku błędnego komunikatu.
Wyszukiwanie, walidacja i zamiana wymagają innych podejść
Ten sam regex może być używany do różnych celów, ale nie każdy sposób dopasowania daje taki sam efekt. Najpierw ustalam, czy chcę znaleźć fragment, potwierdzić cały tekst, czy zmienić dane. Dopiero potem dobieram funkcję i kotwice.
| Cel | Typowe podejście | Na co uważać |
|---|---|---|
| Wyszukanie fragmentu | Wyszukiwanie bez kotwic | Może znaleźć dopasowanie w środku dłuższego tekstu |
| Walidacja całej wartości |
^...$ lub odpowiednik pełnego dopasowania |
Różnice w obsłudze końca linii między silnikami |
| Wyciągnięcie danych | Grupy przechwytujące | Zbyt wiele grup utrudnia późniejsze utrzymanie |
| Zamiana fragmentu | Regex oraz tekst zastępczy | Referencje do grup mają różną składnię w językach |
Przykładowo wzorzec \d+ znajdzie liczby w zdaniu, ale nie sprawdzi, czy całe zdanie składa się wyłącznie z cyfr. Do walidacji całej wartości potrzebny będzie zapis ^\d+$ albo funkcja przeznaczona do pełnego dopasowania.
Przy zamianie można usunąć nadmiarowe spacje wzorcem \s+ i zastąpić je pojedynczą spacją. To praktyczne przy czyszczeniu danych, ale przed wykonaniem operacji na dużym zbiorze zawsze testuję przykłady brzegowe. Jedna zbyt szeroka reguła może zmienić także fragmenty, które miały pozostać nietknięte.
Gdzie wyrażenia regularne mają ograniczenia
Regex jest bardzo dobry w rozpoznawaniu prostych wzorców, ale nie jest uniwersalnym językiem do analizy tekstu. Nie rozumie kontekstu, znaczenia słów ani relacji między elementami dokumentu. Dlatego próba napisania jednego ogromnego wzorca często kończy się kodem trudnym do sprawdzenia i jeszcze trudniejszym do naprawy.
Walidacja adresów e-mail
Da się stworzyć regex, który odrzuci oczywiście błędne adresy e-mail, na przykład pozbawione znaku @. Nie warto jednak próbować odwzorowywać w nim całej formalnej specyfikacji poczty. W praktyce lepiej użyć rozsądnej walidacji formatu, a istnienie adresu potwierdzić przez proces aplikacyjny, na przykład wiadomość aktywacyjną.
HTML, XML i dane zagnieżdżone
Do przetwarzania HTML lub XML lepiej użyć parsera. Regex może zadziałać na bardzo prostym, kontrolowanym fragmencie, ale szybko zawodzi przy atrybutach, zagnieżdżeniach, komentarzach i nietypowym formatowaniu. W testach interfejsu wybieram selektory DOM, role i stabilne identyfikatory zamiast wycinania elementów z kodu strony za pomocą skomplikowanego wzorca.
Wydajność i ryzyko ReDoS
Niektóre złożone regexy mogą działać bardzo długo na odpowiednio przygotowanym tekście. Zjawisko to bywa określane jako catastrophic backtracking, czyli gwałtowny wzrost liczby prób dopasowania. Ma znaczenie zwłaszcza wtedy, gdy wzorzec analizuje dane przesyłane przez użytkownika lub używane w publicznym API.
Żeby ograniczyć ryzyko, unikam niepotrzebnie zagnieżdżonych kwantyfikatorów, testuję długie i nietypowe dane oraz ustawiam limity czasu. Regex używany w teście powinien być nie tylko poprawny, ale też przewidywalny pod względem wydajności.
Przeczytaj również: Playwright po polsku - Stabilne testy E2E od podstaw!
Różnice między silnikami
Składnia nie jest identyczna w JavaScript, Pythonie, Javie, PHP czy narzędziach wykorzystujących PCRE. Różnić się mogą między innymi flagi, obsługa znaków Unicode, lookbehind oraz znaczenie skrótów takich jak \w.
Jeśli test ma działać w kilku technologiach, sprawdzam wzorzec bezpośrednio w każdym używanym środowisku. Szczególnie ostrożnie traktuję \w, bo jego zakres może zależeć od silnika i trybu Unicode. Przy danych użytkownika często bezpieczniej jawnie wskazać dozwolone zakresy znaków.
Jak budować regex, który da się utrzymać
Najlepszy wzorzec to nie zawsze najkrótszy wzorzec. W automatyzacji testów liczy się przede wszystkim to, czy po kilku miesiącach inna osoba zrozumie, co dokładnie jest sprawdzane i dlaczego reguła ma taką postać.
- Zdefiniuj cel i zdecyduj, czy chodzi o wyszukiwanie, pełną walidację czy ekstrakcję.
- Rozpisz poprawne i błędne przykłady, zanim zaczniesz skracać składnię.
- Dodaj kotwice, jeśli dopasowanie ma obejmować całą wartość.
-
Ograniczaj zakres zamiast używać szerokich konstrukcji typu
.*bez wyraźnej potrzeby. - Opisz wzorzec komentarzem albo nazwij stałą tak, aby wskazywała jego przeznaczenie.
- Testuj przypadki brzegowe, w tym pusty tekst, bardzo długą wartość, znaki diakrytyczne i dodatkowe spacje.
W testach automatycznych szczególnie dobrze działa zestaw przypadków pozytywnych i negatywnych. Samo sprawdzenie, że poprawny kod przechodzi, nie daje pewności, że aplikacja odrzuca kod z literówką, złą długością albo niewłaściwym separatorem.
Regex warto też przechowywać poza logiką testu, jeśli jest używany w kilku miejscach. Dzięki temu zmiana formatu identyfikatora nie wymaga poprawiania wielu niemal identycznych fragmentów. Dla bardziej złożonych reguł pomocne są testy jednostkowe samego wzorca, niezależne od całego interfejsu aplikacji.
Od prostego wzorca do stabilnego testu
Najkrócej mówiąc, wyrażenie regularne opisuje kształt tekstu. Może znaleźć numer, sprawdzić kod, wyciągnąć fragment odpowiedzi API albo uelastycznić asercję w teście automatycznym. Jego siła wynika z prostych symboli, które można łączyć w precyzyjne reguły.
Najbezpieczniej zaczynać od małego wzorca, testować go na realnych danych i dopiero później dodawać wyjątki. Gdy dane mają złożoną strukturę, lepiej sięgnąć po parser lub selektor właściwy dla danego formatu. Regex robi największą różnicę wtedy, gdy rozwiązuje konkretny problem, a nie wtedy, gdy zastępuje całe narzędzie do analizy danych.