Programování

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.

12. 10. 2026 · 4 min čtení

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.