Programming

Регулярные выражения

Регулярное выражение (regex) — строка-шаблон, описывающая множество строк, по которой ищут, проверяют и заменяют текст.

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

Регулярное выражение (regex, regexp, в разговоре «регулярка») — строка-шаблон, описывающая множество строк. Вместо перечисления «найди 8-800-555-35-35 или 8-800-555-35-36 или…» шаблон задаёт правило: «восьмёрка, дефис, три цифры, дефис…».

Три типовые задачи: найти подстроку по образцу, проверить формат ввода, заменить по шаблону. Движки regex встроены почти везде — Python, JavaScript, grep, sed, PHP, Java, PostgreSQL, конфиги Nginx. Термин пришёл из теории формальных языков, где «регулярный» — класс языков, распознаваемых конечным автоматом; современные движки давно вышли за эти рамки, но название осталось.

Базовый синтаксис

Шаблон Значение Пример совпадения
. Любой символ, кроме перевода строки a.cabc, a7c
\d \w \s Цифра, буквоцифра/_, пробельный \d\d42
\D \W \S Отрицание предыдущих \Dx
[abc] Любой из перечисленных [аеиоу] → гласная
[^abc] Любой, кроме перечисленных [^0-9] → не цифра
[a-z] Диапазон [a-zA-Zа-яА-Я]
^ $ Начало и конец строки ^Ошибка
\b Граница слова \bкот\b не найдёт «котлета»
| Или cat|dog
(...) Группа с захватом (\d{4})-(\d{2})
(?:...) Группа без захвата (?:ab)+

Квантификаторы — сколько раз

Шаблон Сколько Пример
* 0 или больше \d*
+ 1 или больше \d+2026
? 0 или 1 https?http, https
{3} Ровно 3 \d{3}
{2,5} От 2 до 5 \w{2,5}
{2,} 2 и больше \d{2,}

Жадность — источник половины багов

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

import re

html = "<b>жирный</b> и <i>курсив</i>"
re.findall(r"<.+>", html)    # ['<b>жирный</b> и <i>курсив</i>'] — съел всё
re.findall(r"<.+?>", html)   # ['<b>', '</b>', '<i>', '</i>'] — ленивый, минимум

? после квантификатора делает его ленивым. Ещё надёжнее — запретить лишнее явно: <[^>]+> вообще не даст точке перепрыгнуть через >.

Практика на Python

import re

text = "Заказ 8814 от 2026-07-17, сумма 15000 руб., ivan@example.com"

re.search(r"\d{4}-\d{2}-\d{2}", text).group()     # '2026-07-17'
re.findall(r"\d+", text)                          # ['8814', '2026', '07', '17', '15000']
re.sub(r"\d{4}-\d{2}-\d{2}", "<дата>", text)      # замена
re.split(r",\s*", text)                           # разбиение по шаблону

# именованные группы читаются куда лучше, чем m.group(1)
m = re.match(r"(?P<year>\d{4})-(?P<month>\d{2})", "2026-07")
m.group("year")                                    # '2026'

# компиляция — если шаблон применяется в цикле
pattern = re.compile(r"^ERROR\s+(\S+)", re.MULTILINE)

Флаги: re.IGNORECASE — без учёта регистра, re.MULTILINE^/$ работают на каждой строке, re.VERBOSE — разрешает пробелы и комментарии внутри шаблона.

Те же шаблоны работают в Bash через grep — например, топ IP-адресов из лога:

grep -Eo '[0-9]{1,3}(\.[0-9]{1,3}){3}' access.log | sort | uniq -c | sort -rn

ReDoS — регулярка как способ уронить сервер

Вложенные квантификаторы приводят к катастрофическому бэктрекингу: движок перебирает экспоненциальное число вариантов, и один запрос занимает ядро CPU на минуты.

re.match(r"^(a+)+$", "a" * 30 + "!")   # зависнет надолго

Если шаблон применяется к пользовательскому вводу, это готовая уязвимость — ReDoS. Меры: не вкладывать квантификатор в квантификатор, ограничивать длину входа, а в критичных местах брать движок с линейной гарантией (RE2, regex с таймаутом).

Когда не надо

  • HTML и XML — вложенность регуляркой не разбирается в принципе. Берите парсер (BeautifulSoup, lxml).
  • JSON, CSV — есть готовые библиотеки, они учитывают кавычки и экранирование.
  • Email по-настоящему — полный шаблон из RFC 5322 занимает страницу. Проверьте наличие @ и отправьте письмо со ссылкой подтверждения; это единственная надёжная валидация.
  • Простой поиск подстроки"error" in line быстрее и понятнее любой регулярки.

Отлаживать шаблоны удобно на regex101.com: он показывает разбор по шагам и подсвечивает группы. И помните: regex, который вы писали полчаса, через месяц не прочитает никто — включая вас. Комментируйте (re.VERBOSE) или разбивайте на части.

Связанные термины

  • grep — регулярки в командной строке
  • Python — модуль re
  • Bash — grep, sed и awk в скриптах
  • Парсинг — где regex помогает, а где нужен парсер
  • Конкатенация — соседняя базовая операция над строками

Готовы запустить GPU-задачу?

Запустить GPU-сервер