Urobte Python skripty múdrejšie pomocou regexu: 5 praktických príkladov re
Ak pracujete s reťazcami vo svojich Python skriptoch a píšete zložitú logiku na ich spracovanie, mali by ste sa pozrieť na regulárne výrazy v Pythone. Umožňujú vám popísať vzory namiesto písania procedurálnej logiky. Pozrime sa na niekoľko reálnych príkladov, kde modul re v Pythone robí skripty inteligentnejšie.
Overte potajme zadané vstupy používateľa
Pri overovaní vstupu používateľa bez regexu ste pravdepodobne napísali kód, ktorý sa vám zdal nesprávny. Predpokladajme, že chcete overiť používateľské meno podľa týchto pravidiel:
- Iba písmená, číslice a podčiarkovníky
- Musí začínať písmenom
- Dĺžka medzi 3 a 16 znakmi
Toto je bežná požiadavka. Poďme sa pozrieť, čo musíte urobiť bez použitia Pythonovho modulu re:
def is_valid_username(username):
if len(username) < 3 or len(username) > 16:
return False
if not username[0].isalpha():
return False
for char in username:
if not (char.isalnum() or char == "_"):
return False
return TrueToto funguje, ale je to obsiahle, ľahko sa pri tom urobia chyby a každé nové pravidlo znamená pridanie ďalšej logiky. Presne tu vyniká modul re. Pravidlá popisujete deklaratívne pomocou re.compile() a tento vzor potom používate všade:
import re
USERNAME_PATTERN = re.compile(r"^[a-zA-Z][a-zA-Z0-9_]{2,15}$")
def is_valid_username(username):
return bool(USERNAME_PATTERN.fullmatch(username))
Poďme pochopiť, čo sa deje.
^: Toto označuje začiatok reťazca[a-zA-Z]: Musí začínať písmenom[a-zA-Z0-9_]{2,15}: Povolené znaky a zostávajúca dĺžka$: Toto označuje koniec reťazca
Akonáhle začnete overovať vstupy pomocou re, je ťažké sa k tomu vrátiť. Pravidlá vyjadrujete priamo a Python sa postará o náročnú prácu.
Extrahovať údaje z neporiadneho textu
V určitom okamihu sa každý Python skript stretne s neusporiadaným textom. Log súbory, zachytené pakety, e-maily, extrahované HTML a ďalšie. Výzvou je z toho získať štruktúru bez písania krehkého kódu, ktorý analyzuje riadok po riadku.
Predstavte si, že spracúvate súbor protokolu aplikácie a chcete extrahovať časové značky a chybové správy. Typický riadok protokolu môže vyzerať takto:
[2025-01-02 14:33:21] ERROR: Connection timed out after 30 secondsMôžete to skúsiť takto:
def parse_log_line(line):
if not line.startswith("["):
return None
parts = line.split("]")
timestamp = parts[0][1:]
if "ERROR:" not in parts[1]:
return None
message = parts[1].split("ERROR:")[1].strip()
return timestamp, messageToto funguje pre presný formát, ktorý ste testovali. Ale je to krehké. Extra medzery, chýbajúce zátvorky alebo mierne odlišné znenie môžu logiku zničiť. Navyše je zámer kódu skrytý pod stringovými gymnastikami. S modulom re môžete popísať štruktúru riadku namiesto toho, aby ste ho manuálne rozsekávali.
import re
LOG_PATTERN = re.compile(
r"\[(?P<timestamp>[\d\-: ]+)\]\s+ERROR:\s+(?P<message>.+)"
)
def parse_log_line(line):
match = LOG_PATTERN.search(line)
if not match:
return None
return match.group("timestamp"), match.group("message")
Tu presne hovoríme Pythonu, čo hľadáme: časovú značku v zátvorkách, nasledovanú slovom „ERROR“, nasledovanú zvyškom správy.
Vyčistiť a normalizovať text v jednom riadku
Čistenie textu je jedna z tých úloh, ktorá vyzerá jednoducho, kým ju skutočne nevykonáte. Často sa musíte zaoberať nadbytočnými medzerami, nekonzistentnými oddeľovačmi, náhodnou interpunkciou alebo zvláštnosťami formátovania, ktoré sťažujú ďalšie spracovanie.
Povedzme, že spracovávate text od používateľov a chcete ho normalizovať pred jeho uložením alebo porovnaním. Vaše pravidlá sú:
- Odstrániť medzery na začiatku a na konci
- Nahradiť viacnásobné medzery, tabulátory alebo nové riadky jednou medzerou
- Odstráňte nealfanumerické znaky (okrem medzier)
- Preveďte všetko na malé písmená
Bez použitia re môže typický prístup vyzerať takto:
def clean_text(text):
text = text.strip()
text = text.replace("\n", " ").replace("\t", " ")
while " " in text:
text = text.replace(" ", " ")
cleaned = []
for char in text:
if char.isalnum() or char == " ":
cleaned.append(char)
return "".join(cleaned).lower()Toto nie je hrozné, ale je to hlučné. Následok je rozptýlený naprieč slučkami a opakovanými operáciami. A ak chcete upraviť pravidlá, musíte znova editovať niekoľko riadkov.
S Pythonovým re.sub() môžete popísať vzory chaosu namiesto toho, aby ste ich riešili jeden po druhom.
import re
def clean_text(text):
text = re.sub(r"\s+", " ", text) # normalize whitespace
text = re.sub(r"[^a-zA-Z0-9 ]", "", text) # remove punctuation
return text.strip().lower()To je rovnaká logika, vyjadrená oveľa jasnejšie.
Inteligentné hľadanie a nahrádzanie
Každý programátor v Pythone pozná str.replace(). Je jednoduchý, rýchly a úplne postačujúci, až kým nepotrebujete kontext. V momente, keď vaša náhrada závisí od toho, kde sa niečo nachádza, čo to obklopuje alebo od časti toho, čo ste zhodovali, str.replace() nestačí.
Predstavte si, že pracujete s protokolmi alebo exportovanými údajmi, ktoré obsahujú citlivé informácie, a chcete pred uložením alebo zdieľaním súboru zamaskovať e-mailové adresy.
User john.doe@example.com logged in from 10.0.0.5Chceš toto:
User ***@example.com logged in from 10.0.0.5
Pri použití základných metód reťazcov to rýchlo začne byť nepríjemné:
def mask_email(text):
words = text.split()
masked = []
for word in words:
if "@" in word:
username, domain = word.split("@", 1)
masked.append("***@" + domain)
else:
masked.append(word)
return " ".join(masked)
Toto predpokladá, že e-maily sú oddeľované medzerou, nezvláda dobre interpunkciu a mieša analýzu s logikou nahrádzania. S re.sub() môžete priamo porovnávať e-mailové adresy a nahradiť iba časť, ktorá vás zaujíma.
import re
EMAIL_PATTERN = re.compile(r"([\w.-]+)@([\w.-]+\.\w+)")
def mask_emails(text):
return EMAIL_PATTERN.sub(r"***@\2", text)Tu vykonáva ťažkú prácu Python modul re. Vzor nájde reťazce podobné e-mailu kdekoľvek v texte, zachytávacie skupiny izolujú užívateľské meno a doménu a nahradenie opätovne použije časť zhody cez \2. Toto je hľadanie a nahrádzanie s vedomím kontextu.
Analyzovať polostruktúrované údaje
Aj v špecifickej situácii, keď niektoré údaje nie sú čisto štruktúrované a sú úplne voľnej formy, modul re v Pythone ticho zachraňuje situáciu. Predpokladajme, že máte dané reťazce ako tieto:
name=John age=32 role=admin active=true
Vašou úlohou je premeniť to na slovník. Formát je konzistentný, ale nie je zaručené medzerovanie, poradie ani to, ktoré kľúče sa objavia. Jediné, čo viete, je, že ide o sekvenciu párov kľúč-hodnota. Ako prvý pokus by ste mohli použiť split():
def parse_kv_string(text):
result = {}
parts = text.split()
for part in parts:
if "=" not in part:
continue
key, value = part.split("=", 1)
result[key] = value
return resultToto funguje, kým sa hodnoty nestanú zložitejšími, nezmení sa odsadenie alebo neželáte overovanie. Opäť platí, že logika hľadania dát a ich spracovania je tesne prepojená.
S re.findall() v Pythone môžete priamo popísať štruktúru a nechať motor, aby vykonal skenovanie.
import re
KV_PATTERN = re.compile(r"(\w+)=([^\s]+)")
def parse_kv_string(text):
return dict(KV_PATTERN.findall(text))Ten jediný vzor vyjadruje celý formát: kľúč pripomínajúci slovo, za ktorým nasleduje znak rovnosti (=), a potom hodnota bez medzier. Pythonov modul re extrahuje všetky páry naraz.
Ak ste Python programátor, ktorý sa vyhýbal regexu, začnite pomaly. Na validáciu použite re.fullmatch(). Pri čistení textu skúste re.sub(). Keď vám vzory začnú dávať zmysel, zistíte, že píšete kratšie skripty, ktoré robia viac.





