Шаблоны как крошечный язык
Регулярное выражение (regex) описывает множество строк. Вместо перечисления всех вариантов вы пишете шаблон: «три цифры», «форма, похожая на e-mail», «строки, начинающиеся с ERROR». Языки программирования, редакторы и инструменты для данных встраивают движки regex, чтобы искать, проверять и извлекать текст.
Диалекты regex различаются (JavaScript, Python, PCRE, Rust). Это руководство сосредоточено на понятиях, общих для большинства современных движков, с уклоном в синтаксис в стиле JavaScript, используемый в браузерах. Проверяйте шаблоны интерактивно с помощью инструмента тестирования regex.
Литералы и метасимволы
Большинство символов совпадают сами с собой: cat совпадает с тремя буквами c-a-t по порядку. Метасимволы несут особый смысл: . ^ $ * + ? ( ) [ ] { } \ | (и другие в зависимости от диалекта).
Чтобы сопоставить метасимвол буквально, экранируйте его обратной косой чертой: \. совпадает с точкой. В некоторых языках экранирование строк накладывается на экранирование regex—получается «ад обратных слэшей». Предпочитайте сырые строки (raw), если язык их предлагает.
Классы символов
Квадратные скобки перечисляют допустимые символы: [abc] совпадает с a, b или c. Диапазоны вроде [0-9] совпадают с цифрами. Отрицание [^0-9] совпадает с символом, который не является цифрой.
Сокращённые классы (зависят от flavor) включают \d (цифра), \w (символ слова), \s (пробельный символ). Их точные определения различаются—особенно для Unicode. Когда проверка должна быть точной, предпочитайте явные диапазоны или escapes свойств Unicode, если движок их поддерживает (\p{L} для букв в современном JS).
Якоря
^ совпадает с началом строки (или строки текста в многострочном режиме). $ совпадает с концом. \b совпадает с границей слова. Якоря не потребляют символы; они утверждают позиции.
^\d{5}$ совпадает со строкой ровно из пяти цифр—не с пятью цифрами внутри более длинного текста—когда якоря соблюдаются.
Квантификаторы
Квантификаторы задают повторение:
| Квантификатор | Значение |
|---|---|
* | ноль или больше |
+ | один или больше |
? | ноль или один |
{n} | ровно n |
{n,} | n или больше |
{n,m} | от n до m включительно |
По умолчанию квантификаторы жадные (greedy): они совпадают с максимально возможным объёмом, пока общий шаблон ещё может успешно сработать. Ленивые варианты (*?, +?) совпадают с минимумом. Жадноe совпадение — частая причина сюрпризов вида «мой шаблон съел весь документ».
Группы и альтернация
Скобки ( ... ) создают группы для квантификации подшаблонов и захвата подстрок. (ab)+ совпадает с ab, abab и т.д. Альтернация | выбирает среди вариантов: cat|dog.
Незахватывающие группы (?: ... ) группируют без сохранения захвата—чище, когда нужна только структура.
Именованные захваты есть во многих движках ((?<year>\d{4})) и улучшают читаемость при извлечениях.
Жадноe ловушки и бэктрекинг
Классический проблемный шаблон для определённых входов выглядит как (.*)+ или вложенные неоднозначные квантификаторы. Патологический бэктрекинг может заморозить процесс—ReDoS (regular expression denial of service). Для пользовательских шаблонов в production используйте таймауты, безопасные subset-парсеры или движки с гарантиями линейного времени. Для своих шаблонов предпочитайте конкретные классы символов вместо .*, когда это возможно.
Флаги / модификаторы
Частые флаги:
i— без учёта регистраm—^/$действуют построчноs— точка совпадает с переводами строк (в движках, которые это поддерживают)g— найти все совпадения (global)u— режим Unicode в JavaScript
Флаги существенно меняют смысл; всегда документируйте, какие флаги использует валидатор.
Валидация против извлечения
Валидация спрашивает, совпадает ли весь ввод: часто сочетайте шаблон с якорями начала и конца или используйте API-методы с семантикой полного совпадения. Извлечение находит подстроки: используйте search/global API и группы захвата.
Не притворяйтесь, что свободный e-mail-regex — полноценный RFC-валидатор. Для критичных форматов комбинируйте regex со специализированными парсерами.
Небольшая лестница обучения
- Сопоставить фиксированное слово.
- Добавить класс символов для цифры.
- Квантифицировать цифры через
{n}. - Закрепить шаблон якорями.
- Ввести одну опциональную группу.
- Извлечь захват.
- Только потом пробовать lookahead/lookbehind, если движок их поддерживает.
Прыжок к скопированному «идеальному e-mail-regex» из интернета почти ничему не учит и часто ломается на краевых случаях.
Привычки тестирования
- Ведите таблицу примеров should-match и should-not-match.
- Включайте пустую строку, максимальную длину и образцы Unicode.
- Тестируйте многострочный ввод, когда важны
mили точка поверх переводов строк. - При отладке упрощайте шаблон, пока удивительное совпадение не исчезнет, затем собирайте заново.
Инструмент test-pattern помогает итерировать примеры, прежде чем жёстко вшивать шаблон в код приложения.
Читаемость и сопровождение
Длинные regex — write-once, read-never. Стратегии:
- Разбивать валидацию на несколько небольших проверок.
- Использовать verbose/extended-режим, если доступен (Python
re.X), с комментариями. - Назначать шаблон именованной константе.
- Предпочитать парсеры для вложенных структур (HTML, JSON)—regex неверное средство для произвольной вложенности.
Lookahead и lookbehind (необязательный следующий шаг)
Когда якоря и группы станут привычными, многие движки предлагают lookahead и lookbehind: утверждения, которые проверяют, что следует или предшествует позиции, не потребляя эти символы. Например, положительный lookahead может потребовать, чтобы строка вроде пароля где-то содержала цифру, не сдвигая основной курсор совпадения неуклюжим образом. Эти возможности сильны и легко злоупотребляются; держите их редкими, комментируйте и проверяйте поведение в точном диалекте—поддержка lookbehind и правила фиксированной ширины не одинаковы везде.
Итог
Регулярные выражения описывают формы текста с литералами, классами, квантификаторами, якорями и группами. Они сильны в кратких проверках и извлечениях, когда шаблоны остаются конкретными и протестированными. Учитывайте различия диалектов, избегайте катастрофического бэктрекинга и переходите к настоящим парсерам, когда сложность грамматики перерастает одну строку знаков препинания.