Wyrażenia regularne (regex) to wielokrotnego użytku wzorce dopasowujące określone sekwencje znaków w tekście - wyobraź sobie superusprawnione narzędzie "znajdź", które działa w niemal każdym języku programowania. Niezależnie od tego, czy walidujesz adres e-mail, wyciągasz numer telefonu z formularza, czy parseujesz plik logów, kilka dobrze dobranych wzorców regex poradzi sobie z 90% typowych zadań. Ten przewodnik zbiera najbardziej przydatne wzorce, dokładnie wyjaśnia, co robi każdy z nich, i pokazuje, jak je dostosować do własnych potrzeb.
Spis treści
Szybkie przypomnienie składni regex
Zanim przejdziemy do konkretnych wzorców, oto ściągawka z podstawowych elementów składni, które będziesz spotykać wielokrotnie. Nawet jeśli masz już doświadczenie z regex, warto mieć je zebrane w jednym miejscu.
| Token | Znaczenie | Przykładowe dopasowanie |
|---|---|---|
.
|
Dowolny znak z wyjątkiem nowej linii |
a.c
dopasowuje
abc
,
a1c
|
\d
|
Dowolna cyfra (0-9) |
\d\d
dopasowuje
42
|
\w
|
Znak słowny (litery, cyfry, podkreślnik) |
\w+
dopasowuje
hello_world
|
\s
|
Biały znak (spacja, tabulator, nowa linia) |
\s+
dopasowuje wiele spacji
|
^
/
$
|
Początek / koniec ciągu znaków |
^\d+$
dopasowuje tylko
123
|
{n,m}
|
Od n do m powtórzeń |
\d{2,4}
dopasowuje od
12
do
1234
|
[abc]
|
Klasa znaków - dowolny z: a, b, c |
[aeiou]
dopasowuje dowolną samogłoskę
|
(?:...)
|
Grupa nieprzechwytująca | Grupuje bez zapisywania backreference |
(?=...)
|
Pozytywny lookahead | Sprawdza, co następuje dalej, bez konsumowania znaków |
Przewodnik MDN Web Docs po wyrażeniach regularnych to najlepsze pojedyncze źródło wiedzy o składni regex w JavaScript. Większość wzorców z tego artykułu działa bezpośrednio w Pythonie, PHP, Javie i Ruby - różnice dotyczą głównie flag.
Walidacja adresów e-mail
Walidacja e-mail to klasyczny przypadek użycia regex - i jednocześnie ten, w którym większość programistów popełnia błąd, próbując być zbyt restrykcyjnymi. Specyfikacja
RFC 5322
technicznie dopuszcza adresy takie jak
"very unusual"@example.com
, z którymi praktycznie żaden wzorzec regex sobie nie radzi. Do walidacji danych wejściowych w 99% przypadków wystarczy pragmatyczny wzorzec:
^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$
Co robi każda część wzorca:
-
[a-zA-Z0-9._%+\-]+- część lokalna (przed @); dopuszcza kropki, znaki plus, myślniki i podkreślniki -
@- dosłowny znak @ -
[a-zA-Z0-9.\-]+- nazwa domeny, łącznie z subdomenami -
\.[a-zA-Z]{2,}- TLD o długości co najmniej 2 znaków (.io, .com, .museum)
URL i adresy internetowe
Dopasowywanie wzorców URL przydaje się wszędzie - od wyciągania linków z czystego tekstu po walidację adresu strony podanego przez użytkownika w formularzu.
https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*)
-
https?- dopasowuje zarównohttp, jak ihttps -
(?:www\.)?- opcjonalny prefiks www -
[-a-zA-Z0-9@:%._+~#=]{1,256}- znaki nazwy hosta, do 256 znaków -
\.[a-zA-Z0-9()]{1,6}- TLD -
\b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*)- opcjonalna ścieżka, query string i fragment
Jeśli chcesz tylko walidować (a nie wyciągać), opakuj wzorzec kotwicami
^
i
$
.
Numery telefonów
Numery telefonów są wyjątkowo niejednolite, bo formatowanie różni się znacznie w zależności od kraju i przyzwyczajeń użytkownika. Dwa wzorce pokrywają większość scenariuszy:
Format USA/Kanada (NANP)
^(\+1[-.\s]?)?(\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}$
Dopasowuje:
555-867-5309
,
(555) 867 5309
,
+1.555.867.5309
,
5558675309
Format międzynarodowy (E.164)
^\+[1-9]\d{6,14}$
E.164 to format używany przez większość API telefonicznych (Twilio, AWS SNS). Zaczyna się od
+
i kodu kraju, bez spacji ani znaków interpunkcyjnych.
Daty i czas
Dopasowywanie wzorców dat jest powszechne w parserach logów, walidatorach formularzy i pipeline'ach przetwarzania danych. Wybór formatu zależy od źródła danych wejściowych.
ISO 8601 (YYYY-MM-DD)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
Format amerykański (MM/DD/YYYY)
^(0[1-9]|1[0-2])\/(0[1-9]|[12]\d|3[01])\/\d{4}$
Czas w formacie 24-godzinnym (HH:MM lub HH:MM:SS)
^([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?$
Pamiętaj, że te wzorce walidują format, a nie logikę kalendarza. Zaakceptują na przykład
2024-02-31
(31 lutego nie istnieje). Do ścisłej walidacji dat parsuj wynik za pomocą biblioteki dat dostępnej w Twoim języku programowania.
Walidacja siły hasła
Reguły dotyczące haseł zazwyczaj wymagają mieszanki różnych typów znaków i minimalnej długości. Lookaheady pozwalają to zrealizować elegancko, bez potrzeby wykonywania wielu oddzielnych sprawdzeń.
Minimum 8 znaków, co najmniej jedna wielka litera, jedna mała litera i jedna cyfra
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$
Silne hasło: 8+ znaków, wielka litera, mała litera, cyfra i znak specjalny
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$
Każdy
(?=.*[...])
to lookahead, który przeszukuje cały string w poszukiwaniu co najmniej jednego pasującego znaku. Końcowy fragment
.{8,}
wymusza minimalną długość. Możesz zamienić
{8,}
na
{12,}
, aby wymagać co najmniej 12 znaków - zgodnie z wytycznymi
NIST SP 800-63B
.
Adresy IP
IPv4
^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$
Ten wzorzec poprawnie odrzuca wartości takie jak
999.0.0.1
, dopasowując każdy oktet jawnie w zakresie 0-255.
IPv6 (uproszczony)
^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$
Ten wzorzec obsługuje pełny format 8-grupowy. Dla notacji skróconej (np.
::1
dla loopback) wzorzec staje się znacznie bardziej złożony - w takim przypadku parsowanie za pomocą biblioteki sieciowej jest bardziej niezawodne niż regex.
HTML i znaczniki
Kilka celowanych wzorców jest tu naprawdę przydatnych. Ogólna zasada "nie parsuj HTML za pomocą regex" nadal obowiązuje w przypadku pełnych dokumentów - do tego celu używaj właściwego parsera DOM, takiego jak BeautifulSoup lub DOMParser. Jednak do konkretnych, ograniczonych zadań regex sprawdza się doskonale.
Usuwanie wszystkich tagów HTML
<[^>]*>
Wyciąganie zawartości z konkretnego tagu (np. <title>)
([^<]*)<\/title>
Grupa przechwytująca nr 1 zawiera tekst tytułu.
Dopasowywanie szesnastkowych kodów kolorów HTML
#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})\b
Dopasowuje zarówno 3-cyfrowy skrót (
#fff
), jak i pełną 6-cyfrową formę (
#ffffff
).
Codzienne wzorce użytkowe
Te wzorce pojawiają się regularnie w różnych typach projektów.
Slug (string przyjazny dla URL)
^[a-z0-9]+(?:-[a-z0-9]+)*$
Dopasowuje ciągi takie jak
my-blog-post-2024
. Bez wielkich liter, bez myślników na początku i końcu, bez podwójnych myślników.
Numer karty kredytowej (podstawowy format, bez spacji)
^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$
-
Zaczyna się od
4- Visa (13 lub 16 cyfr) -
Zaczyna się od
51-55- Mastercard (16 cyfr) -
Zaczyna się od
34lub37- Amex (15 cyfr) -
Zaczyna się od
6011lub65- Discover (16 cyfr)
Normalizacja białych znaków (zwijanie wielu spacji)
\s{2,}
Zastąp dopasowania pojedynczą spacją, aby wyczyścić chaotyczne dane wejściowe od użytkownika lub tekst ze scrapingu.
Tylko cyfry
^\d+$
Tylko znaki alfanumeryczne
^[a-zA-Z0-9]+$
Dopasowanie linii zawierającej słowo (bez uwzględniania wielkości liter, z flagą)
^.*\bword\b.*$
Granica słowa
\b
zapobiega dopasowaniu
word
wewnątrz
password
.
Wyciąganie numerów wersji (semver)
\bv?(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.]+))?(?:\+([a-zA-Z0-9.]+))?\b
Przechwytuje numer major, minor, patch, etykietę pre-release i metadane buildu ze stringów takich jak
v2.14.0-beta.1+build.42
.
Flagi i praktyczne wskazówki
Wzorce regex zachowują się różnie w zależności od zastosowanych flag. Oto te, których potrzebujesz najczęściej:
| Flaga | JS | Python | Działanie |
|---|---|---|---|
| Bez uwzględniania wielkości liter |
i
|
re.IGNORECASE
|
Traktuje wielkie i małe litery jako równoważne |
| Globalna (znajdź wszystkie) |
g
|
re.findall()
|
Zwraca wszystkie dopasowania, nie tylko pierwsze |
| Wieloliniowa |
m
|
re.MULTILINE
|
^
i
$
kotwiczą do granic linii, nie do granic całego stringa
|
| Dotall |
s
|
re.DOTALL
|
.
dopasowuje również znaki nowej linii
|
Kilka nawyków, które zaoszczędzą Ci czasu podczas debugowania:
- Zawsze testuj na przypadkach brzegowych - pusty string, maksymalna długość, znaki Unicode i ciągi, które są prawie, ale nie do końca poprawne.
-
Używaj grup nieprzechwytujących
(?:...)gdy nie potrzebujesz dopasowanej zawartości - są szybsze i czytelniejsze niż grupy przechwytujące. -
Kotwicz wzorce walidacyjne
za pomocą
^i$, żeby poprawnie wyglądający podciąg wewnątrz niepoprawnego stringa nie przeszedł przez filtr. -
Uważaj na katastrofalne backtracking
- zagnieżdżone kwantyfikatory, takie jak
(a+)+, mogą powodować zawieszanie silnika regex na spreparowanych danych wejściowych. Trzymaj kwantyfikatory proste i konkretne. - Korzystaj z testera regex podczas budowania wzorców. regex101.com pokazuje na żywo rozbicie dopasowania, wyjaśnia każdy token i pozwala przełączać się między PCRE, JavaScript, Pythonem i innymi wariantami.
Testuj i waliduj wzorce regex bez zgadywania
Budowanie niezawodnych wzorców regex do walidacji danych wejściowych jest szybsze, gdy masz pod ręką odpowiednie narzędzia. Odkryj nasze bezpłatne narzędzia dla programistów do czyszczenia, sprawdzania i transformacji tekstu za pomocą wzorców regex i nie tylko.
Wypróbuj nasze bezpłatne narzędzia →
Zachłanne kwantyfikatory (takie jak
.*
) dopasowują jak najwięcej znaków, a następnie cofają się. Leniwe kwantyfikatory (takie jak
.*?
) dopasowują jak najmniej. Na przykład dla stringa
bold
wzorzec
<.*>
dopasowuje cały string, podczas gdy
<.*?>
dopasowuje tylko
. Używaj leniwych kwantyfikatorów przy wyciąganiu zawartości między ogranicznikami.
W większości tak, ale istnieją różnice. Moduł
re
w Pythonie używa składni w stylu PCRE i obsługuje nazwane grupy za pomocą
(?P
. JavaScript używa nieco innej składni flag i nie obsługuje lookbehind w starszych silnikach (przed ES2018). Przy pracy między językami trzymaj się wspólnego podzbioru: klas znaków, kwantyfikatorów, kotwic i podstawowych grup.
Regex doskonale nadaje się do walidacji formatu w środowisku produkcyjnym - jest stosowany praktycznie w każdym frameworku webowym. Ryzyko wiąże się ze źle napisanymi wzorcami, które umożliwiają ataki ReDoS (regex denial-of-service) poprzez katastrofalne backtracking. Unikaj zagnieżdżonych kwantyfikatorów, twórz konkretne wzorce i zawsze ustawiaj rozsądny limit długości danych wejściowych, zanim w ogóle uruchomi się regex.
W większości popularnych silników są one równoważne dla danych wejściowych ASCII. Różnica pojawia się przy Unicode:
\d
w niektórych silnikach (jak Python 3 w trybie Unicode) dopasowuje cyfry z innych systemów pisma, na przykład cyfry arabsko-indyjskie. Jeśli chcesz mieć pewność, że dopasowujesz wyłącznie cyfry ASCII 0-9, użyj jawnie
[0-9]
. W przypadku większości walidacji formularzy webowych ta różnica nie ma znaczenia.
Potrzebujesz dwóch rzeczy: flagi
dotall
(żeby
.
dopasowywało znaki nowej linii) oraz ewentualnie flagi
multiline
(żeby
^
i
$
kotwiczył do każdej linii, a nie do całego stringa). W JavaScript użyj
/pattern/ms
. W Pythonie połącz
re.DOTALL | re.MULTILINE
. Bez flagi dotall
.
zatrzymuje się na znakach nowej linii i wzorzec nie obejmie wielu linii.