🧠 Продвинутые советы по работе с Regex в Python
Всегда компилируй регулярные выражения. Это ускоряет работу при многократном использовании, делает код чище и упрощает тестирование.
import re
RE_EMAIL = re.compile(r"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b", re.I)
emails = RE_EMAIL.findall(text)
Используй raw-строки и re.VERBOSE, чтобы regex был читаемым, а не выглядел как случайный набор символов.
RE_DATE = re.compile(r"""
\b
(?P<year>\d{4})-(?P<month>0[1-9]|1[0-2])-(?P<day>0[1-9]|[12]\d|3[01])
\b
""", re.VERBOSE)
Если группа не нужна в выводе - делай её non-capturing (?:...). Это уменьшает расходы памяти и путаницу с индексами групп.
re.findall(r"(?:https?://)?(?:www\.)?example\.com/\S+", text)
Используй правильные якоря.
\A и \Z безопаснее для валидации, чем
^ и $, которые зависят от флага MULTILINE.
re.match(r"\A\d+\Z", "123\n")
Контролируй код и ставь ограничения.
Бесконтрольный .* — частая причина зависаний и ReDoS.
re.search(r"<[^>]{0,2000}>", html)
Lookahead и lookbehind позволяют искать текст без захвата. Это мощный инструмент для точных выборок.
m = re.search(r"(?<=token=)[^\s]+", s)
Различай search, match и fullmatch. Для валидации почти всегда нужен fullmatch.
re.fullmatch(r"[a-z0-9_-]{3,32}", username)
Если замена содержит логику - используй функцию.
RE_NUM = re.compile(r"\d+")
masked = RE_NUM.sub(lambda m: "*" * len(m.group(0)), s)
Тестируй regex на “враждебных” данных: длинные строки, повторения.
Это помогает избежать ошибок.
Если стандартного
re не хватает, используй библиотеку
regex - она поддерживает таймауты и более мощные конструкции.
pip install regex
Regex в продакшене - это не магия. Это контроль, ограничения,
читаемость и тестирование.
@pythonl