Regulární výrazy v Pythonu: modul re prakticky a česky
Jak používat regulární výrazy v Pythonu – search vs. match, skupiny, pojmenované skupiny, sub s funkcí, příznaky, chamtivé kvantifikátory a typické české vzory.
Regulární výrazy jsou malý jazyk pro hledání vzorů v textu. V Pythonu s nimi pracuje modul re. Jsou mocné, ale snadno se z nich stane nečitelná šifra. Projdeme si to podstatné na praktických příkladech a ukážeme i to, kdy regex nepoužívat.
Vždy raw stringy
import re
re.search(r"\d+", "Objednávka 4521")
Prefix r vypne zpracování zpětných lomítek Pythonem. Bez něj by "\b" znamenalo backspace, ne hranici slova. Od Pythonu 3.12 dostanete za neplatné escape sekvence jako "\d" dokonce SyntaxWarning.
Hlavní funkce
| Funkce | Co dělá |
|---|---|
re.search(vzor, text) |
první shoda kdekoli v textu, nebo None |
re.match(vzor, text) |
shoda jen na začátku textu |
re.fullmatch(vzor, text) |
celý text musí odpovídat |
re.findall(vzor, text) |
seznam všech shod |
re.finditer(vzor, text) |
iterátor objektů Match |
re.sub(vzor, nahrada, text) |
nahrazení |
re.split(vzor, text) |
rozdělení |
Pro validaci vstupu používejte fullmatch. Častá chyba je match, který ověří jen začátek:
re.match(r"\d{3}", "123abc") # shoda!
re.fullmatch(r"\d{3}", "123abc") # None
Základní syntaxe
| Vzor | Význam |
|---|---|
. |
libovolný znak kromě nového řádku |
\d / \D |
číslice / ne-číslice |
\w / \W |
znak slova (v Pythonu 3 včetně č, ř, ž…) / opak |
\s |
bílý znak |
\b |
hranice slova |
^ / $ |
začátek / konec (řádku s re.M) |
[abc], [^abc], [a-z] |
třída znaků |
*, +, ? |
0+, 1+, 0–1 opakování |
{3}, {2,5} |
přesný počet / rozsah |
(…) |
skupina |
(?:…) |
skupina bez zachycení |
a\|b |
alternativa |
V Pythonu 3 jsou \w a \d u řetězců ve výchozím stavu Unicode, takže \w+ zachytí i „žluťoučký“. \d ale zachytí i jiné číslice (např. arabské). Pokud chcete jen 0–9, použijte [0-9] nebo příznak re.ASCII.
Skupiny a pojmenované skupiny
text = "Faktura FV-2026-0042 ze dne 12.10.2026"
m = re.search(r"FV-(\d{4})-(\d+)", text)
if m:
print(m.group(0)) # FV-2026-0042
print(m.group(1)) # 2026
print(m.groups()) # ('2026', '0042')
Pojmenované skupiny jsou čitelnější:
m = re.search(r"(?P<den>\d{1,2})\.(?P<mesic>\d{1,2})\.(?P<rok>\d{4})", text)
print(m["den"], m["mesic"], m["rok"])
print(m.groupdict()) # {'den': '12', 'mesic': '10', 'rok': '2026'}
Pozor na findall se skupinami: vrací obsah skupin, ne celou shodu.
re.findall(r"(\d+) Kč", "Hrnek 149 Kč, tričko 399 Kč") # ['149', '399']
Nahrazování
# sjednocení mezer
re.sub(r"\s+", " ", " hodně mezer\tzde ").strip()
# přehození data na ISO formát pomocí odkazů na skupiny
re.sub(r"(\d{1,2})\.(\d{1,2})\.(\d{4})", r"\3-\2-\1", "12.10.2026")
# '2026-10-12'
Jako náhradu lze předat funkci – užitečné pro výpočty:
def s_dph(m: re.Match) -> str:
cena = int(m["cena"])
return f"{round(cena * 1.21)} Kč"
re.sub(r"(?P<cena>\d+) Kč", s_dph, "Cena 100 Kč bez DPH")
# 'Cena 121 Kč bez DPH'
Chamtivé vs. líné kvantifikátory
html = "<b>tučně</b> a <b>ještě</b>"
re.findall(r"<b>.*</b>", html) # ['<b>tučně</b> a <b>ještě</b>']
re.findall(r"<b>.*?</b>", html) # ['<b>tučně</b>', '<b>ještě</b>']
* bere co nejvíc, *? co nejméně. (A na skutečné HTML použijte parser jako BeautifulSoup, ne regex.)
Příznaky
re.findall(r"chyba", log, re.IGNORECASE)
re.findall(r"^ERROR.*$", log, re.MULTILINE) # ^ a $ pro každý řádek
re.search(r"<pre>(.*?)</pre>", html, re.DOTALL) # . zahrnuje i \n
Složitější vzory se dají komentovat pomocí re.VERBOSE:
PSC = re.compile(r"""
\b
(?P<psc>\d{3}\s?\d{2}) # 110 00 nebo 11000
\b
""", re.VERBOSE)
Kompilace
re.compile() se vyplatí hlavně pro čitelnost a znovupoužití. Modul re si navíc nedávno použité vzory cachuje sám, takže výkonnostní rozdíl bývá malý.
TELEFON = re.compile(r"(?:\+420\s?)?\d{3}\s?\d{3}\s?\d{3}")
TELEFON.findall("Volejte +420 777 123 456 nebo 602123456")
Užitečné české vzory
PSC = r"\b\d{3}\s?\d{2}\b"
ICO = r"\b\d{8}\b" # tvar, ne kontrolní součet
DATUM = r"\b\d{1,2}\.\s?\d{1,2}\.\s?\d{4}\b"
CASTKA = r"\d{1,3}(?:[ ]\d{3})*(?:,\d{2})?\s?Kč"
je nezlomitelná mezera, kterou často obsahují částky zkopírované z webu nebo PDF.
Regex ověří tvar, ne platnost. IČO má kontrolní číslici, datum 31.02.2026 neexistuje. Platnost kontrolujte kódem (datetime.strptime, výpočet kontrolního součtu).
Kdy regex nepoužívat
- E-mail – úplný regex je obří. Ověřte
@a tečku, a pak pošlete potvrzovací e-mail. - HTML, XML, JSON – použijte parser.
- Jednoduché operace –
"abc" in text,text.startswith(),text.split(",")jsou čitelnější i rychlejší. - Nedůvěryhodné vzory od uživatelů – špatně napsaný regex (např.
(a+)+$) může mít exponenciální složitost (ReDoS).
Testování vzorů
Vzory si ladte interaktivně na regex101.com s nastavenou příchutí Python. Zobrazí vysvětlení každé části výrazu i skupiny. Hotový vzor pak pokryjte testem s pozitivními i negativními příklady.