Cel: po tym rozdziale:
- rozpoznasz wzorce w tekście (np. e-mail, telefon, datę),
- wyciągniesz potrzebne fragmenty,
- zrobisz sprytne zamiany (sprzątanie tekstu),
- poznasz flagi i lookaroundy (bez strachu).
1) Start: moduł re i „surowe” łańcuchy
Regex to wzorzec zapisany jako tekst. W Pythonie piszemy go jako surowy łańcuch (z r"..."), żeby backslash \ nie robił niespodzianek.
import re
wzorzec = r"\d\d-\d\d" # np. 12-34
tekst = "Kod: 12-34 i 99-01"
m = re.search(wzorzec, tekst) # pierwsze dopasowanie
print(m.group()) # 12-34
re.search– znajduje pierwsze dopasowanie.- Chcesz wszystkie? Użyj
findallalbofinditer:
print(re.findall(wzorzec, tekst)) # ['12-34', '99-01']
for dop in re.finditer(wzorzec, tekst):
print(dop.span(), dop.group())
2) Najważniejsze klocki składni (po ludzku)
.– dowolny znak (poza nową linią)\d– cyfra,\w– „znak słowa” (litera/cyfra/_),\s– biały znak+– 1 lub więcej,*– 0 lub więcej,?– 0 lub 1{m,n}– od m do n razy, np.\d{2,4}[]– zestaw znaków, np.[A-ZĄĆŁÓŚŻŹ]()– grupowanie i łapanie fragmentu|– „albo”^/$– początek / koniec linii (lub całego tekstu – zależy od flag)
Przykład – polski kod pocztowy DD-DDD:
kod = r"^\d{2}-\d{3}$"
print(bool(re.fullmatch(kod, "80-241"))) # True
print(bool(re.fullmatch(kod, "80241"))) # False
re.fullmatch wymaga dopasowania całości.
3) Grupy (w tym nazwane) – wyciągasz tylko to, co ważne
email = r"([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[A-Za-z]{2,})"
m = re.search(email, "Kontakt: ala.kowalska@example.com")
if m:
nazwa, domena = m.group(1), m.group(2)
print(nazwa, domena)
Nazwane grupy są czytelniejsze:
email_named = r"(?P<user>[a-zA-Z0-9._%+-]+)@(?P<host>[a-zA-Z0-9.-]+\.[A-Za-z]{2,})"
m = re.search(email_named, "Napisz: test+info@firma.pl")
print(m.group("user"), m.group("host"))
4) Zamiana w tekście – re.sub (tak sprzątasz tekst)
Proste podmiany:
tekst = "Ala ma kota"
czysto = re.sub(r"\s+", " ", tekst) # wiele spacji → jedna
print(czysto) # Ala ma kota
„Funkcyjna” zamiana – pełna kontrola:
import re
email_named = r"(?P<user>[a-zA-Z0-9._%+-]+)@(?P<host>[a-zA-Z0-9.-]+\.[A-Za-z]{2,})"
def maskuj_email(m):
user = m.group("user")
host = m.group("host")
return f"{user[:2]}***@{host}"
mask = re.sub(email_named, maskuj_email, "Kontakt: jan.kowalski@firma.pl")
print(mask) # Kontakt: ja***@firma.pl
5) Flagi – kiedy chcesz inaczej
re.IGNORECASE/re.I– ignoruj wielkość literre.MULTILINE/re.M–^i$działają dla każdej liniire.DOTALL/re.S– kropka.obejmuje też nową linięre.VERBOSE/re.X– dziel wzorzec na linie i komentuj
wzorzec = re.compile(r"""
^\s* # opcjonalne spacje na początku
(?P<key>\w+)\s*:\s* # klucz:
(?P<val>.+?) # wartość (najkrótsze dopasowanie)
\s*$ # opcjonalne spacje na końcu
""", re.X | re.M)
txt = "imie: Ala\nmiasto: Gdańsk"
for m in wzorzec.finditer(txt):
print(m.group("key"), "->", m.group("val"))
re.compile(...) opłaca się, gdy wzorca używasz wielokrotnie.
6) Lookaroundy – spójrz obok, ale nie „zjadaj”
(?=...)– pozytywny lookahead: dalej musi być…(?!...)– negatywny lookahead: dalej nie może być…(?<=...)– pozytywny lookbehind: przed dopasowaniem musi być…(?<!...)– negatywny lookbehind: przed dopasowaniem nie może być…
Przykład – tylko liczby przed „PLN”:
ceny = "25 PLN, 9.99 USD, 100 PLN"
print(re.findall(r"\d+(?:\.\d+)?(?=\s*PLN)", ceny)) # ['25', '100']
7) Bezpieczeństwo i zdrowy rozsądek
- Użytkownik może wpisać
.+(– w regexie to specjalne znaki.
Chcesz dopasować dosłownie? Użyjre.escape:szukane = input("Czego szukasz? ") wzorzec = re.compile(re.escape(szukane), re.I) print(bool(wzorzec.search("To jest bezpieczne wyszukiwanie."))) - Regex nie zawsze jest potrzebny. Czasem
split,in,startswithsą prostsze i szybsze. - Bardzo skomplikowane wzorce – trudne w utrzymaniu. Używaj
re.VERBOSEi komentarzy.
8) Małe, życiowe przykłady
A) „Na oko” walidacja telefonu PL (do nauki, nie perfekcyjna produkcja):
tel = r"^\+?48?\s?[- ]?\d{3}[- ]?\d{3}[- ]?\d{3}$"
for t in ["+48 600-700-800", "600700800", "48 600 700 800", "abc"]:
print(t, "->", bool(re.fullmatch(tel, t)))
B) Wyciąganie wszystkich e-maili z tekstu
emails = re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[A-Za-z]{2,}", """
Kontakt: ala@firma.pl, bok@example.com, test+help@dom.pl
""")
print(emails)
C) Normalizacja spacji i tabów
tekst = "Ala\t ma \t kota"
print(re.sub(r"\s+", " ", tekst).strip()) # Ala ma kota
D) Zamiana dat „DD/MM/RRRR” → „RRRR-MM-DD”
def repl(m):
d, mth, y = m.group("d"), m.group("m"), m.group("y")
return f"{y}-{mth.zfill(2)}-{d.zfill(2)}"
wz = re.compile(r"(?P<d>\d{1,2})/(?P<m>\d{1,2})/(?P<y>\d{4})")
print(re.sub(wz, repl, "Spotkanie: 1/9/2025, backup: 12/10/2025"))
9) Typowe pułapki (i jak ich uniknąć)
| Pułapka | Co się dzieje | Jak żyć |
|---|---|---|
. nie łapie nowej linii | dopasowania „urywają się” | użyj flagi re.S (DOTALL) |
| Niechciane ogromne dopasowanie | „zachłanne” .+ zjada za dużo | użyj wersji „leniwych” .+? |
| Literówki w wzorcu | wynik „niby działa” ale źle | testuj na kilku przykładach |
| Zbyt skomplikowany regex | trudny w utrzymaniu | rozbij na części, użyj re.X i komentarzy |
10) Ćwiczenia (koniecznie spróbuj)
- Kropki do jednej – zamień
...lub..na. - Adresy IP – wyciągnij z tekstu wzorce
123.45.67.89 - Kod pocztowy – sprawdź
DD-DDD(pełne dopasowanie) - Ceny w PLN – wyciągnij liczby (całe i z częścią dziesiętną) przed
PLN - Wielka litera – znajdź słowa zaczynające się od dużej litery (np. imiona)
Podsumowanie
Umiesz już:
- szukać (
search,findall,finditer) i dopasowywać całość (fullmatch), - używać grup (w tym nazwanych) i robić zamiany (
sub, także funkcją), - stosować flagi, lookaroundy i kompilować wzorce,
- wybierać, kiedy regex ma sens, a kiedy lepiej użyć prostszych metod.

