📖 Теория: регулярные выражения

⚡ Кратко

Regex — язык шаблонов: \d — цифра, \w — буква/цифра/_ , . — любой символ, ^/$ — начало/конец строки. Квантификаторы + * ? задают повторы. Группы (...) извлекают части совпадения.

Что такое регулярное выражение

Регулярное выражение (regular expression, RegEx) — это шаблон, описывающий набор строк. С его помощью можно искать, проверять, разделять и заменять текст.

  • Проверка формата: email, телефон, дата.
  • Поиск: найти все числа или теги в тексте.
  • Замена: привести даты к единому формату.
  • Разделение: разбить строку по нескольким разделителям.

Модуль re

Все функции regex в стандартной библиотеке находятся в модуле re:

  • re.search(pattern, string) — первое совпадение в любой части строки.
  • re.match(pattern, string) — совпадение только в начале строки.
  • re.findall(pattern, string) — список всех совпадений.
  • re.finditer(pattern, string) — итератор объектов Match.
  • re.sub(pattern, repl, string) — замена всех совпадений.
  • re.split(pattern, string) — разделение строки по шаблону.

Сырые строки r"..."

В шаблонах много обратных слэшей. В обычных строках Python интерпретирует \ как начало управляющей последовательности, поэтому всегда используйте сырые строки:

import re

# Хорошо: шаблон содержит ровно то, что видим
print(re.findall(r"\d+", "Price: 123"))

# Плохо: без r тот же шаблон превращается в "d+"
print(re.findall("\d+", "Price: 123"))  # не найдёт цифры

Классы символов

Специальные символы задают категории:

  • \d — любая цифра, \D — всё кроме цифр.
  • \w — буквы, цифры и _, \W — остальное.
  • \s — пробельные символы, \S — непробельные.
  • . — любой символ, кроме \n (без флага re.DOTALL).

Свои наборы задаются квадратными скобками [...]:

  • [a-z] — любая строчная латинская буква.
  • [A-Z] — любая заглавная.
  • [0-9] — то же, что \d.
  • [^0-9] — всё, кроме цифр.

Квантификаторы

Квантификаторы управляют количеством повторений:

  • + — один или более раз.
  • * — ноль или более раз.
  • ? — ноль или один раз.
  • {n} — ровно n раз.
  • {n,}n и более раз.
  • {n,m} — от n до m раз.

По умолчанию квантификаторы жадные — захватывают максимум символов. Добавьте ?, чтобы сделать их ленивыми:

import re

text = "<div>Hello</div><div>World</div>"
print(re.findall(r"<.*>", text))   # жадно: один большой кусок
print(re.findall(r"<.*?>", text))  # лениво: каждый тег отдельно

Якоря

Якоря не ищут символы, а проверяют позицию:

  • ^ — начало строки.
  • $ — конец строки.
  • \b — граница слова.
  • \B — не граница слова.

Альтернативы

Оператор | работает как «ИЛИ»:

import re

text = "Meeting on 2024-05-10 or 10/05/2024"
dates = re.findall(r"\d{4}-\d{2}-\d{2}|\d{2}/\d{2}/\d{4}", text)
print(dates)

Группы

Круглые скобки (...) создают группы. Они позволяют извлекать части совпадения или применять квантификаторы к части шаблона:

import re

match = re.search(r"Order ID: (\d+), Invoice No: (\d+)", "Order ID: 12345, Invoice No: 67890")
if match:
    print(match.group(1))  # 12345
    print(match.group(2))  # 67890

Негруппирующие скобки (?:...) нужны для логики, но не попадают в результат:

import re

print(re.findall(r"(?:USD|EUR|GBP) (\d+)", "USD 100, EUR 200"))  # ['100', '200']

Флаги

Флаги меняют поведение поиска:

  • re.IGNORECASE (или re.I) — игнорировать регистр.
  • re.DOTALL (или re.S) — точка . совпадает и с \n.
  • re.MULTILINE (или re.M) — ^ и $ работают для каждой строки.
import re

text = "Python is fun\npython is useful"
print(re.findall(r"^python", text, re.IGNORECASE | re.MULTILINE))  # ['Python', 'python']

Когда regex не нужен

Для простых операций удобнее и быстрее встроенные методы строк:

text = "hello world"

# Проще и понятнее, чем регулярка
if "world" in text:
    print("found")

parts = text.replace(",", " ").split()  # разбить по пробелам/запятым
Проверить по докуентации: флаги re.DOTALL и re.MULTILINE, а также рекомендации по замене простых regex на методы строк описаны в официальной документации модуля re и методов строк.