Популярные паттерны Regex, которые каждый разработчик должен сохранить в закладки

Справочник по шаблонам regex с подсветкой синтаксиса на тёмном фоне редактора

Регулярные выражения - это переиспользуемые шаблоны для поиска и сопоставления последовательностей символов в тексте. Можно представить их как мощный инструмент поиска, который работает практически в любом языке программирования. Валидация email-адресов, очистка номеров телефонов из форм, парсинг лог-файлов - десяток грамотно подобранных regex-паттернов закроет 90% задач. В этом руководстве собраны самые практичные шаблоны с подробным разбором каждого.

Краткий справочник по синтаксису

Прежде чем разбирать конкретные паттерны, полезно освежить в памяти базовые токены. Даже если ты уже работал с регулярными выражениями, иметь всё это в одном месте удобно.

Токен Значение Пример совпадения
. Любой символ, кроме перевода строки a.c совпадает с abc , a1c
\d Любая цифра (0-9) \d\d совпадает с 42
\w Словесный символ (буквы, цифры, знак подчёркивания) \w+ совпадает с hello_world
\s Пробельный символ (пробел, табуляция, перевод строки) \s+ совпадает с несколькими пробелами
^ / $ Начало / конец строки ^\d+$ совпадает только с 123
{n,m} От n до m повторений \d{2,4} совпадает от 12 до 1234
[abc] Класс символов - любой из a, b, c [aeiou] совпадает с любой гласной
(?:...) Незахватывающая группа Группирует без сохранения обратной ссылки
(?=...) Позитивный lookahead Проверяет, что следует дальше, не потребляя символы

Руководство по регулярным выражениям на MDN Web Docs - лучший единый справочник по regex-синтаксису JavaScript. Большинство паттернов ниже напрямую переносятся в Python, PHP, Java и Ruby с незначительными различиями в флагах.

Валидация email

Email - классический сценарий применения regex, и именно здесь большинство разработчиков допускают ошибку, пытаясь сделать паттерн слишком строгим. Спецификация RFC 5322 технически допускает адреса вроде "very unusual"@example.com , с которыми почти ни один regex не справится. Для 99% задач валидации пользовательского ввода достаточно прагматичного паттерна:

^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$

Что делает каждая часть:

  • [a-zA-Z0-9._%+\-]+ - локальная часть (до символа @); допускает точки, знаки плюса, дефисы, подчёркивания
  • @ - символ @ буквально
  • [a-zA-Z0-9.\-]+ - доменное имя, включая поддомены
  • \.[a-zA-Z]{2,} - TLD длиной не менее 2 символов (.io, .com, .museum)
Regex не может подтвердить, что email-адрес реально существует и принимает письма. Для всего важного обязательно отправляй письмо с подтверждением.

URL и веб-адреса

Паттерны для URL нужны как для извлечения ссылок из обычного текста, так и для валидации поля с сайтом, которое заполняет пользователь.

https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*)
  • https? - совпадает как с http , так и с https
  • (?:www\.)? - необязательный префикс www
  • [-a-zA-Z0-9@:%._+~#=]{1,256} - символы имени хоста, до 256 символов
  • \.[a-zA-Z0-9()]{1,6} - TLD
  • \b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*) - необязательные путь, строка запроса и фрагмент

Если нужна только валидация (без извлечения), оберни паттерн якорями ^ и $ .

Номера телефонов

Номера телефонов - заведомо неудобный случай, потому что форматирование сильно варьируется в зависимости от страны и привычек пользователя. Два паттерна покрывают большинство сценариев:

Формат США/Канады (NANP)

^(\+1[-.\s]?)?(\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}$

Совпадает с: 555-867-5309 , (555) 867 5309 , +1.555.867.5309 , 5558675309

Международный формат (E.164)

^\+[1-9]\d{6,14}$

E.164 - это формат, который используется в большинстве телефонных API (Twilio, AWS SNS). Начинается с + и кода страны, без пробелов и знаков препинания.

Если нужно большее, чем базовая проверка формата, - например, убедиться, что номер является действующим мобильным номером в конкретной стране, - используй специализированную библиотеку libphonenumber (библиотека Google с открытым исходным кодом, доступна для Java, JavaScript, Python и других языков).

Даты и время

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

ISO 8601 (YYYY-MM-DD)

^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

Американский формат (MM/DD/YYYY)

^(0[1-9]|1[0-2])\/(0[1-9]|[12]\d|3[01])\/\d{4}$

24-часовое время (HH:MM или HH:MM:SS)

^([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?$

Обрати внимание: эти паттерны проверяют формат, но не календарную логику. Например, 2024-02-31 (31 февраля) пройдёт валидацию. Для строгой проверки дат разбирай значение средствами стандартной библиотеки дат уже после проверки regex.

Проверка надёжности пароля

Требования к паролям обычно включают сочетание разных типов символов и минимальную длину. Lookahead-ы позволяют сделать это чисто, без нескольких отдельных проверок.

Минимум 8 символов, хотя бы одна заглавная, одна строчная буква и одна цифра

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$

Надёжный: 8+ символов, заглавные, строчные буквы, цифра и специальный символ

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$

Каждый (?=.*[...]) - это lookahead, который просматривает всю строку в поисках хотя бы одного подходящего символа. Финальный .{8,} задаёт минимальную длину. Можно заменить {8,} на {12,} для требования минимум 12 символов - это соответствует рекомендациям NIST SP 800-63B .

IP-адреса

IPv4

^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$

Паттерн корректно отклоняет значения вроде 999.0.0.1 , явно сопоставляя каждый октет в диапазоне 0-255.

IPv6 (упрощённый вариант)

^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$

Обрабатывает полный формат из 8 групп. Для сжатой нотации (например, ::1 для loopback) паттерн значительно усложняется - в таком случае надёжнее воспользоваться сетевой библиотекой, а не regex.

HTML и разметка

Для HTML есть несколько действительно полезных точечных паттернов. Общий совет «не парси HTML с помощью regex» по-прежнему актуален для полных документов - для этого используй нормальный DOM-парсер, например BeautifulSoup или DOMParser. Но для конкретных, ограниченных задач regex вполне справится.

Удалить все HTML-теги

<[^>]*>

Извлечь содержимое конкретного тега (например, <title>)

([^<]*)<\/title>

Захватывающая группа 1 содержит текст заголовка.

Сопоставить hex-коды цветов HTML

#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})\b

Совпадает как с трёхсимвольным сокращением ( #fff ), так и с полной шестисимвольной записью ( #ffffff ).

Универсальные утилитарные паттерны

Эти паттерны постоянно встречаются в самых разных проектах.

Slug (строка, пригодная для URL)

^[a-z0-9]+(?:-[a-z0-9]+)*$

Совпадает со строками вроде my-blog-post-2024 . Без заглавных букв, без дефисов в начале и конце, без двойных дефисов.

Номер банковской карты (базовый формат, без пробелов)

^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$
  • Начинается с 4 - Visa (13 или 16 цифр)
  • Начинается с 51-55 - Mastercard (16 цифр)
  • Начинается с 34 или 37 - Amex (15 цифр)
  • Начинается с 6011 или 65 - Discover (16 цифр)
Никогда не храни номера карт в открытом виде. Этот паттерн предназначен только для клиентской обратной связи по формату ввода. Реальная проверка карт должна проходить через PCI-совместимый процессор, например Stripe или Braintree.

Нормализация пробелов (сворачивание нескольких пробелов в один)

\s{2,}

Заменяй совпадения одним пробелом, чтобы очистить неаккуратный пользовательский ввод или спарсенный текст.

Только цифры

^\d+$

Только буквенно-цифровые символы

^[a-zA-Z0-9]+$

Поиск строки, содержащей слово (без учёта регистра с флагом)

^.*\bword\b.*$

Граница слова \b предотвращает совпадение word внутри password .

Извлечение номеров версий (semver)

\bv?(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.]+))?(?:\+([a-zA-Z0-9.]+))?\b

Захватывает мажорную, минорную, патч-версию, метку пре-релиза и метаданные сборки из строк вроде v2.14.0-beta.1+build.42 .

Флаги и практические советы

Поведение regex-паттернов зависит от применяемых флагов. Вот наиболее востребованные из них:

Флаг JS Python Эффект
Без учёта регистра i re.IGNORECASE Считает заглавные и строчные буквы одинаковыми
Глобальный (найти все) g re.findall() Возвращает все совпадения, а не только первое
Многострочный m re.MULTILINE ^ и $ привязываются к границам строк, а не всей строки целиком
Dotall s re.DOTALL . совпадает в том числе с символами перевода строки

Несколько привычек, которые сэкономят время при отладке:

  • Всегда тестируй на граничных случаях - пустая строка, максимальная длина, Unicode-символы и строки, которые почти, но не совсем валидны.
  • Используй незахватывающие группы (?:...) , когда содержимое совпадения не нужно - это быстрее и чище, чем захватывающие группы.
  • Закрепляй паттерны для валидации якорями ^ и $ , чтобы валидная подстрока внутри невалидной строки не проскользнула незамеченной.
  • Остерегайся катастрофического backtracking-а - вложенные квантификаторы вроде (a+)+ могут привести к зависанию regex-движка на специально подобранных входных данных. Держи квантификаторы простыми и конкретными.
  • Используй онлайн-тестер regex при построении паттернов. regex101.com показывает разбор совпадений в реальном времени, объясняет каждый токен и позволяет переключаться между PCRE, JavaScript, Python и другими диалектами.
Инструменты для сопоставления regex-паттернов и валидации ввода

Тестируй и проверяй regex-паттерны без лишних догадок

Создавать надёжные regex-паттерны для валидации ввода гораздо быстрее, когда под рукой есть нужные инструменты. Попробуй наши бесплатные утилиты для разработчиков - очищай, проверяй и преобразовывай текст с помощью regex-паттернов и не только.

Попробовать бесплатные инструменты →

Жадные квантификаторы (например, .* ) захватывают как можно больше символов, а затем откатываются назад. Ленивые квантификаторы (например, .*? ) захватывают как можно меньше. Например, для строки bold паттерн <.*> совпадает со всей строкой, тогда как <.*?> совпадает только с . Используй ленивые квантификаторы при извлечении содержимого между разделителями.

В основном да, но различия есть. Модуль re в Python использует синтаксис в стиле PCRE и поддерживает именованные группы через (?P...) . JavaScript использует немного другой синтаксис флагов и не поддерживает lookbehind в старых движках (до ES2018). Для кроссплатформенного кода придерживайся общего подмножества: классы символов, квантификаторы, якоря и базовые группы.

Regex вполне подходит для валидации формата в продакшене - он используется практически в каждом веб-фреймворке. Риски связаны с плохо написанными паттернами, которые допускают ReDoS-атаки (отказ в обслуживании через regex) за счёт катастрофического backtracking-а. Избегай вложенных квантификаторов, делай паттерны конкретными и всегда устанавливай разумное ограничение длины входных данных до запуска regex.

В большинстве распространённых движков они эквивалентны для ASCII-ввода. Разница проявляется при работе с Unicode: \d в некоторых движках (например, Python 3 в режиме Unicode) совпадает с цифрами из других систем письма, в частности с арабско-индийскими цифрами. Если нужны строго ASCII-цифры от 0 до 9, используй [0-9] для однозначности. Для большинства задач валидации веб-форм это различие несущественно.

Нужны две вещи: флаг dotall (чтобы . совпадал с переводами строк) и, возможно, флаг multiline (чтобы ^ и $ привязывались к каждой строке, а не ко всей строке целиком). В JavaScript используй /pattern/ms . В Python комбинируй re.DOTALL | re.MULTILINE . Без dotall символ . останавливается на переводах строк и паттерн не охватит несколько строк.