Regulární výrazy v Pythonu
V Pythonu máme řadu funkcí, které můžeme použít pro práci s regulárními výrazy. Projdeme si ty základní. Funkce jsou v modulu re
, který je součástí Pythonu a můžeš ho importovat pomocí příkazu import re
na začátku programu.
Ověření formátu
Často potřebujeme ověřit, jestli máme zadaná data ve správném formátu. Např. telefonní čísla, rodná čísla, ISBN u knih, poštovní směrovací čísla, e-maily nebo čísla bankovního účtu mají jasně definovaný formát.
Zkusme si nejprve zadat rodné číslo. Víme, že rodné číslo se skládá ze 6 číslic, které kódují datum narození, a tří nebo čtyř číslic, které identifikují konkrétního člověka. Regulární výraz, který by číslo ověřil, je \d{9,10}
.
Regulární výraz můžeme vytvořit pomocí funkce compile()
z modulu re
. Před řetězec s regulárními výrazy píšeme r
, abychom Pythonu dali vědět, co je daný řetězec zač.
import re
regularni_vyraz = re.compile(r"\d{9,10}")
rezetec = "9511121234"
print(regularni_vyraz.match(rezetec))
rezetec = "ahoj"
print(regularni_vyraz.match(rezetec))
Pokud funkce match
došla k závěru, že se řetězec shoduje s regulárním výrazem, vrátí objekt Match
. S ním později budeme pracovat. Pokud by však funkce došla k závěru, že se řetězce s regulárním výrazem neshoduje, vrátí hodnotu označovanou jako None
, tj. prázdnou hodnotu.
Otázka: Často je rodné číslo zapisováno ve formátu s podtržítkem, které odděluje datum narození od zbytku. Jak upravíme regulární výraz, aby akceptoval oba formáty, tj. formát s podtržítkem i bez podtržítka?
Přísnější ověření formátu
Pokud chceš ověřit, jestli řetězec odpovídá zadanému výrazu a není tam nic navíc, můžeš použít funkci fullmatch
, která funguje stejně jako funkce match()
.
import re
regularni_vyraz = re.compile(r"\d{9,10}")
rezetec = "9511121234"
print(regularni_vyraz.match(rezetec))
rezetec = "9511121234$ je moje rodné číslo"
print(regularni_vyraz.fullmatch(rezetec))
Zapojení podmínky
Pojďme nyní zapojit do akce podmínku. Můžeme třeba uživateli vypsat, jestli jím zadaná hodnota je správná. Výsledek volání funkce match()
můžeme vložit přímo do podmínky, protože podmínka, které nevložíme operátor na porovnávání (např. ==
) funguje takto:
- Pokud podmínce vložíme nějaký smysluplný výraz, vyhodnotí ho jako pravda.
- Pokud podmínce vložíme prázdnou hodnotu
None
, vyhodnotí ji jako nepravda.
import re
regularni_vyraz = re.compile(r"\d{9,10}")
vstup = input("Zadej rodné číslo: ")
hledani = regularni_vyraz.fullmatch(vstup)
if hledani:
print("Rodné číslo je v pořádku!")
else:
print("Nesprávné rodné číslo!")
E-maily
Pokud např. dostaneme e-mail info@czechitas.cz
, víme, že je v pořádku. E-mail info@czechitascz
by ale v pořádku nebyl, protože "koncovka" "cz"
(v řeči počítačů doména prvního řádu) musí být oddělena tečkou.
import re
regularni_vyraz = re.compile(r"\w+@\w+\.cz")
email = input("Zadej e-mail: ")
hledani = regularni_vyraz.fullmatch(email)
if hledani:
print("E-mail je v pořádku!")
else:
print("Nesprávný e-mail!")
Vyhledávání
Kromě ověřování správného formátu můžeme použít regulární výrazy i k vyhledávání. Například funkce findall
vrátí ze zadaného řetězce všechny podřetězce, které odpovídají danému regulárnímu výrazu, jako seznam.
Následující program například z deníku lékaře vyhledá rodná čísla všech pacientů, které lékař zmínil.
zapis = """
Zápisy o provedených vyšetřeních:
Pacient 6407156800 trpěl bolestí zad a byl poslán na vyšetření.
Pacientka 8655057477 přišla na kontrolu po zranění kotníku.
Do ordinace telefonovala pacientka 7752126712, které byl elektronicky vydán recept na Paralen.
"""
import re
regularni_vyraz = re.compile(r"\d{9,10}")
vysledky = regularni_vyraz.findall(zapis)
for vysledek in vysledky:
print(vysledek)
Nahrazování
Uvažujme, že máme nějakém textu provést anonymizaci, tj. vymazat všechny osobní údaje. K tomu můžeme využít funkci sub()
, která nahradí všechny podřetězce, které odpovídají regulárnímu výrazu, námi zadanou hodnotou.
zapis = """
Zápisy o provedených vyšetřeních:
Pacient 6407156800 trpěl bolestí zad a byl poslán na vyšetření.
Pacientka 8655057477 přišla na kontrolu po zranění kotníku.
Do ordinace telefonovala pacientka 7752126712, které byl elektronicky vydán recept na Paralen.
"""
import re
regularni_vyraz = re.compile(r"\d{9,10}")
anonymniZapis = regularni_vyraz.sub("X" * 9, zapis)
print(anonymniZapis)
Cvičení: Regulární výrazy v Pythonu
Uživatelské jméno
Náš systém vyžaduje od uživatele zadání uživatelského jména. Uživatelské jméno smí obsahovat pouze malá písmena a smí být maximálně 8 znaků dlouhé. Požádej uživatele o zadání uživatelského jména a pomocí regulárního výrazu vyhodnoť, zda je zadané správné.
E-mail s tečkou
Uprav program na ověření e-mailu tak, aby akceptoval i e-maily, které mají v první části tečku, např. jiri.pesik@python.cz.
Záznamy
Uvažujme aplikaci, která si ukládá informace o činnosti uživatelů do textového souboru. Příklad souboru je níže.
zaznamy = """
searchNumber: pavca.czechitas action: search phone number of user dita
user: pavca action: send sms to phone number +420728123456
user: jirka: action: send 2 sms to phone number +420734123456
"""
- Napiš program, který vypíše všechna telefonní čísla, která jsou v textovém souboru zmíněna.
- Nahraď tato telefonní čísla nějakým řetězcem (např. "XXX"), aby nebyla v záznamech dostupná.
Adresy stránek
Adresy webových stránek zpravidla začínají záhadným shlukem písmen http:// nebo https://. Například náš web najdete pod adresou https://kodim.cz. Zkrátka HTTP nebo HTTPS je ve skutečnosti označení protokolu, což je nějaký popis toho, jak by měla vypadat komunikace mezi dvěma zařízeními. Standardního tvaru můžeme využít, abychom z textu vytáhli všechny adresy. Napiš program, který z proměnné email_s_radami
vytáhne všechny webové stránky, které jsou tam zmíněny.
email_s_radami = """
Ahoj,
posílám ti pár tipů, kam se podívat. https://realpython.com nabízí spoustu článků i kurzů. http://docs.python.org nabízí tutoriál i rozsáhlou dokumentaci. http://www.learnpython.org nabízí hezky strukturovaný kurz pro začátečníky, rozebírá ale i nějaká pokročilejší témata. https://www.pluralsight.com je placený web, který ale kvalitou kurzů víceméně nemá konkurenci. Určitě ale sleduj i web https://www.czechitas.cz a přihlašuj se na naše kurzy!
"""
IP adresy
Počítačové sítě jsou ve skutečnosti postavené na číselných adresách, které jsou označeny jako IP adresy. Každá IP adresy je čtveřice čísel v rozsahu 0 až 255, které jsou odděleny tečkou. Například IP adresy webu Czechitas v internetu je 51.68.166.161. My ale pro zjednodušení budeme kontrolovat pouze to, zda je číslo v rozsahu 0 až 299.
Uvažuj, že vytváříš aplikaci, která pošle testovací zprávu (tzv. ping) počítači s nějaou IP adresou. Napiš program, která požádá uživatele o IP adresu a zkontroluj, zda je adresa platná. Např. adresa 325.125.100.128 není platná (první číslo je větší než 255), adresa 152.145.146 také není platá (jde o trojici čísel, nikoli čtveřici), adresa 192.168.1.0 je platná (čtveřice čísel v daném rozsahu).
Práce s kódem
Chceš pomoci firmě, která vyvinula e-mailového klienta pro český trh. Níže je kousek kódu, který generuje popisky políček pro zadání adres příjemců, příjemců v kopii, příjemců ve skryté kopii a tlačítka pro odeslání nebo uložení. Nyní by firma ráda expandovala na německý trh. Bohužel vývojáři vkládali popisky do aplikace jako řetězce a ztratili přehled o řetězcích, které v aplikaci mají a které je potřeba je přeložit.
- Zkopíruj si následující kód, uložený jako řetězec, do svého programu.
- Vyhledej v programu všechny řádky, kde je ukládán řetězec do proměnné, např. řádek
sender_field_title = "Příjemce"
. - Pomocí dalšího regulárního výrazu vytáhni z každého řádku samotný řetězec (může být i s uvozovkami), např.
"Příjemce"
.
kod = """
sender_field_title = "Příjemce"
copy_field_title = "Kopie"
if blind_copy == True:
blind_copy_title = "Skrytá kopie"
if action == "send":
button_title = "Odeslat"
else:
button_title = "Uložit koncept"
"""