Tech Handbook Null Yard

Wyrażenia regularne (Regex) - kompendium praktyczne

Regex to rodzina języków wzorców, a nie jeden identyczny standard we wszystkich programach. Składnia grep/POSIX, JavaScript, Python i PCRE jest podobna, ale różni się szczegółami, dlatego przed użyciem zaawansowanych konstrukcji warto wiedzieć, jakiego engine używa dane narzędzie.

Powiązane tematy: Programowanie w shellu, Visual Studio Code, Vi, Vim, gVim i Neovim oraz Python.

1. Czym jest regex

Wyrażenie regularne opisuje wzorzec tekstu.

Przykłady zastosowań:

  • wyszukiwanie,
  • walidacja,
  • zamiana,
  • parsowanie prostych formatów,
  • filtrowanie logów,
  • praca w edytorze,
  • grep, sed, JavaScript, Python.

Regex jest bardzo użyteczny, ale łatwo go nadużyć. Jeżeli format ma pełny parser, często lepiej użyć parsera.

2. Najprostszy wzorzec

Regex:

cat

pasuje do:

cat
concatenate
category

3. Znaki specjalne

Najczęstsze:

.  dowolny znak
^  początek
$  koniec
*  zero lub więcej
+  jeden lub więcej
?  zero lub jeden
[] klasa znaków
() grupa
|  alternatywa
\  escape

4. Kropka

a.c

pasuje do:

abc
a-c
a c

Jeśli chcesz dosłowną kropkę:

\.

5. Początek i koniec

^hello$

pasuje tylko do całego:

hello

Nie pasuje do:

hello world
say hello

6. Klasy znaków

[abc]

jeden z: a, b, c.

Zakres:

[a-z]
[A-Z]
[0-9]

Negacja:

[^0-9]

7. Skróty

Często:

\d cyfra
\w znak słowa
\s whitespace

Negacje:

\D
\W
\S

Znaczenie \w może się różnić zależnie od silnika i trybu Unicode.

8. Kwantyfikatory

a*     0+
a+     1+
a?     0 lub 1
a{3}   dokładnie 3
a{2,5} od 2 do 5
a{2,}  co najmniej 2

9. Grupy

(ab)+

pasuje do:

ab
abab
ababab

10. Alternatywa

cat|dog

11. Grupowanie alternatywy

^(cat|dog)$

pasuje dokładnie do cat lub dog.

12. Grupy przechwytujące

(\d{4})-(\d{2})-(\d{2})

Dla:

2026-09-19

grupy:

1 = 2026
2 = 09
3 = 19

13. Grupa nieprzechwytująca

W wielu silnikach:

(?:abc)

Grupuje bez tworzenia numerowanej grupy.

14. Named groups

Przykład JavaScript:

(?<year>\d{4})-(?<month>\d{2})

Nazwane grupy poprawiają czytelność.

15. Greedy i lazy

Greedy:

".*"

Lazy:

".*?"

Dla:

"a" "b"

greedy może złapać całość, a lazy pierwszy najmniejszy fragment.

16. Lookahead

Positive:

foo(?=bar)

pasuje do foo, jeśli dalej jest bar.

Negative:

foo(?!bar)

17. Lookbehind

Jeżeli silnik wspiera:

(?<=prefix)\d+

Nie każdy silnik ma identyczne możliwości.

18. Flagi

Popularne:

i  case-insensitive
m  multiline
s  dotall
g  global

JavaScript:

const re = /error/gi;

19. JavaScript

Test:

const re = /^\d{4}-\d{2}-\d{2}$/;
console.log(re.test("2026-09-19"));

Match:

const result = "id=123".match(/\d+/);

Replace:

"hello world".replace(/world/, "regex");

20. Python

import re

if re.search(r"error", text, re.I):
    print("found")

Raw strings r"..." ograniczają problem podwójnego escapowania.

21. grep

grep -E 'error|warning' app.log

Case-insensitive:

grep -Ei 'error|warning' app.log

22. sed

Zamiana:

sed -E 's/[0-9]+/NUMBER/g' file.txt

23. VS Code / Vim

Edytory potrafią wyszukiwać i zamieniać przy użyciu regex.

Przykład:

Znajdź:

foo([0-9]+)

Zamień:

bar$1

Składnia referencji do grup zależy od narzędzia.

24. Walidacja emaila

Nie próbuj odtwarzać całego RFC ogromnym regexem.

Praktyczna walidacja formularza powinna być rozsądna, a prawdziwym potwierdzeniem adresu jest np. wysłanie wiadomości weryfikacyjnej.

25. Regex a HTML

Nie używaj regexu jako pełnego parsera HTML.

HTML ma strukturę, nesting i wiele wyjątków.

Użyj parsera DOM.

26. Czytelność

Jeżeli regex robi się duży:

  • dodaj komentarz,
  • podziel problem,
  • użyj named groups,
  • rozważ parser.

27. Testowanie

Zawsze testuj:

  • poprawne dane,
  • błędne dane,
  • pusty string,
  • znaki Unicode,
  • bardzo długie wejście.

28. ReDoS

Źle skonstruowane regexy mogą mieć bardzo kosztowny backtracking.

Nie uruchamiaj skomplikowanych wzorców na dowolnie długich danych użytkownika bez analizy.

29. Przykłady

IPv4 - prosty wzorzec składniowy:

^(\d{1,3}\.){3}\d{1,3}$

Uwaga: dopuszcza np. 999.999.999.999. Walidacja semantyczna wymaga dodatkowej logiki.

Slug:

^[a-z0-9]+(?:-[a-z0-9]+)*$

Prosty identyfikator:

^[A-Za-z_][A-Za-z0-9_]*$

30. Co trzeba umieć

  • czytać klasy znaków,
  • używać anchors,
  • stosować kwantyfikatory,
  • grupować,
  • robić search/replace,
  • rozumieć greedy/lazy,
  • korzystać z regex w grep, JS i Pythonie,
  • wiedzieć, kiedy regex nie jest dobrym narzędziem.

Źródła referencyjne

  • POSIX regular expressions: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap09.html
  • MDN regular expressions: https://developer.mozilla.org/docs/Web/JavaScript/Guide/Regular_expressions
  • Python re: https://docs.python.org/3/library/re.html