Перейти к основному содержимому

Регулярные выражения — синтаксис с нуля

Разработчику Аналитику Тестировщику

Предыдущий шаг: введение и лаборатория.
Следующий: группы и замена.
Готовые шаблоны для работы — в рецептах и командной строке и лаборатории с разбором по блокам.


Зачем отдельная статья про синтаксис

Регулярное выражение — это мини-язык внутри строки. Один пропущенный \ или якорь $ меняет смысл с "проверить email" на "найти @ где угодно". Здесь разбирается алфавит этого языка: из чего собирают шаблон, как его читать слева направо и как по шагам проверять себя на реальных строках.

После этой статьи вы сможете:

  • читать чужой шаблон по блокам, а не "узнавать целиком";
  • отличать поиск подстроки от проверки всей строки;
  • собирать маски для логина, даты, времени, пути к файлу;
  • понимать, когда пора перейти к группам и флагам.
Как учиться

На каждый новый символ (\d, ^, {2,5}) сразу вбивайте мини-шаблон в лаборатории или на regex101.com. Теория без пяти строк текста в поле "Тест" почти не запоминается.


Как движок "читает" текст

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

Строка для примеров:

user_12 вошёл в систему
ШаблонЧто происходитРезультат
userбуквы user подрядсовпадение user
Userрегистр другойнет (без флага i)
userпоиск с позиции после user_12нет на этом месте; движок мог найти раньше

Шаблон user в тексте xuser_y тоже найдёт подстроку user внутри слова. Чтобы искать отдельное слово, позже понадобятся границы \b или якоря.

Первое совпадение — не всегда "самое логичное" для человека: движок берёт самое левое успешное. Для всех вхождений нужен флаг g или цикл в коде — флаги и жадность.


Пошаговая сборка шаблона

Удобный порядок работы (тот же применяют в Регулярные выражения — рецепты и командная строка):

  1. Словами — что считается успехом? "Строка целиком — дата" или "в логе есть ERROR".
  2. Якоря — нужны ли ^ и $ (форма) или поиск подстроки (лог).
  3. Литералы — фиксированный текст: [, @, ://.
  4. Классы — "цифра", "буква", "не пробел".
  5. Квантификаторы — сколько раз повторять.
  6. Проверка — 5–10 реальных строк + 2 "злых" (пустая, с пробелом, кириллица).
ЗадачаЯкоряТипичный каркас
Поле формы^$^[...]{мин,макс}$
Поиск в файленетлитералы + классы
Одна строка лога целиком^$дата + время + уровень + сообщение

Литералы — "ищи как написано"

Литерал — символ, который в данном месте шаблона означает "найди такой же символ в тексте". Обычно это буквы, цифры и часть знаков препинания.

ШаблонТекстРезультат
12user_1212 внутри слова
_user_12подчёркивание
вошёлuser_12 вошёл в системукириллица как литералы

Какие символы экранировать

В шаблоне спецсимволы имеют отдельный смысл (см. экранирование). В литеральном фрагменте их пишут с \ или помещают в класс [...].

СимволЗачем экранировать
. * + ? ^ $ [ ] ( ) { } | \управляющий смысл в regex
-внутри [ ] может означать диапазон
#в некоторых оболочках — комментарий (зависит от движка)

В коде обратный слэш сам по себе спецсимвол: строка "\d" в Python — это символ d с предупреждением. Используйте сырые строки r"\d" / @"\d" — подробнее в конце статьи.


Точка . — "любой один символ"

. = ровно один символ, кроме перевода строки \n (если не включён флаг sРегулярные выражения — флаги и жадность).

ШаблонТекстЧто найдёт
u.eruseruser (s — "любой один")
u.eru_eru_er
u.eruerнет (нужен ровно один символ между u и er)

Точка не означает "сколько угодно символов". Для нуля и более повторений — *, для одного и более — +.

Чтобы найти настоящую точку (IP, расширение файла), пишут \..

ОшибкаШаблонТекст 3.14
Точка как "любой"\d.\d+подойдёт и 3x14
Точка как литерал\d\.\d+только с точкой

Класс символов [ ... ]

В квадратных скобках задают один допустимый символ на текущей позиции.

ШаблонСмысл
[abc]a, b или c
[a-z]строчная латинская буква
[A-Za-z0-9]буква или цифра
[._-]точка, подчёркивание или дефис
[0-9]то же, что \d в ASCII-цифрах

Пример: [Tt]heThe или the.

Внутри [ ] точка — обычная точка. Шаблон ar[.] ищет a, r и ..


Дефис в классе

- между двумя символами задаёт диапазон:

ЗаписьСмысл
[a-z]от a до z
[A-Z]заглавные латинские
[0-9]цифры

Чтобы искать буквальный дефис, поставьте его в начало или конец класса: [-az] или [az-].


Отрицание — [^ ... ]

^ сразу после [ — "любой один символ, кроме перечисленных":

ШаблонСмысл
[^0-9]всё, кроме цифры
[^@\s]+подряд символы без @ и без пробела
[^\n]+строка до перевода строки (упрощённо "всё до \n")
Путаница с кареткой

^ в начале всего шаблона — "начало строки". ^ сразу после [ — "не этот набор". Это разные роли одного знака.


Когда класс лучше точки

ЗадачаСлабоНадёжнее
Содержимое HTML-тега<.*><[^>]+>
До пробела.*[^\s]+
Только буквы.*[A-Za-z]+

Сокращения \d, \w, \s и "отрицания"

КодОбычно значитПример
\dцифра 0–9\d{4} → год
\wбуква, цифра, _ (часто только ASCII)\w+user_12
\sпробел, таб, перевод строки\s+ → пробелы
\Dне цифра
\Wне "слово"
\Sне пробел\S+ → "слово" без пробелов

Кириллица: \w в JavaScript не совпадает с п или ё. Для русского текста:

[а-яА-ЯёЁ0-9_]+

В JavaScript с флагом u — Unicode-классы \p&#123;L&#125; (буква), \p&#123;N&#125; (число). Проверяйте в лаборатории на своих строках.

Текст\w+[а-яА-ЯёЁ]+
приветчасто нетда
user_12датолько user без _12 при чисто кириллическом классе

Для смешанного логина используйте явный объединённый класс: [A-Za-zа-яА-ЯёЁ0-9_]+.


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

Квантификатор относится к предыдущему атому — одному символу, классу или (позже) группе.

СимволСколько разПримерПодходит к
*0 и большеab*cac, abc, abbc
+1 и большеab+cabc, не ac
?0 или 1colou?rcolor, colour
{3}ровно 3\d{3}123
{2,4}от 2 до 4\d{2,4}12, 1234
{2,}2 и больше\d{2,}99, 12345
{,6}до 6.{,6}не более 6 любых символов

Пример: [a-z]* — ноль или больше строчных латинских букв.

.* — ноль или больше любых символов; по умолчанию жадно (тянет максимум). Подробно — Регулярные выражения — флаги и жадность.


Жадность на пальцах

Текст: aaa, шаблон a+ — совпадение aaa (все три). Шаблон a+? — ленивый, минимум; для одной буквы a результат тот же, разница видна на .* между маркерами.


Пустые совпадения

a* на тексте bbb даёт нулевое совпадение в начале (ноль букв a). В коде при подсчёте всех match это иногда удивляет — смотрите документацию движка.


Якоря ^ и $

СимволСмысл
^начало строки (с флагом m — начало каждой строки в тексте)
$конец строки

Без якорей шаблон ищет подстроку. С якорями на всём шаблоне — всю строку целиком (валидация поля).

ШаблонСтрокаРезультат
oknot okесть (ok внутри)
^ok$not okнет
^ok$okда
^[0-9]+$42нет (пробелы)
^[0-9]+$42да

Для "строка без пробелов по краям" иногда пишут ^\S+$ или обрезают пробелы в коде до regex.

В .NET также встречаются \A (начало всего текста) и \Z (конец) — полезно при многострочных строках без флага m.


Экранирование \

Нужен символВ шаблоне
точка\.
плюс\+
звёздочка\*
вопрос\?
скобки$ $ \[ \]
слэш\\

В коде Python


import re

# Плохо: "\d" — не цифра
re.search("\d+", "42")
# Хорошо:
re.search(r"\d+", "42")

В коде C#

Regex.IsMatch("42", @"\d+");

В редакторе (VS Code / Cursor)

В поле поиска с включённым regex один \ обычно достаточен: \d+.


Сквозной разбор — логин пользователя

Правила (упрощённо):

  • от 3 до 16 символов;
  • только латиница, цифры, _ и -;
  • первый символ — буква.

Шаблон:

^[a-z][a-z0-9_-]{2,15}$
ЧастьЗначение
^начало строки
[a-z]первая буква — строчная латинская
[a-z0-9_-]дальше буква, цифра, _ или -
{2,15}ещё от 2 до 15 символов (итого 3…16)
$конец
СтрокаПодходит?Почему
jo-hn_doeда
john12да
Joнетзаглавная в начале
abнет2 символа
jo hnнетпробел
adminдазарезервированные имена отсекают в бизнес-логике, не в regex

Вариант с флагом i (первая буква любого регистра, остальное по правилам) — отдельный шаблон или нормализация в нижний регистр до проверки.


Сквозной разбор — пароль (только длина и символы)

Сложные правила ("цифра + спецсимвол") удобнее через проверки вокруг. Здесь — только длина и набор символов:

^[A-Za-z\d@$!%*?&]{8,32}$
ЧастьЗначение
{8,32}от 8 до 32 символов
классразрешённые символы

Цифру и спецсимвол добавят отдельными (?=.*\d) в статье Регулярные выражения — проверки вокруг совпадения.


Сквозной разбор — email (форма, упрощённо)

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
БлокСмысл
^...$вся строка — один адрес
[a-zA-Z0-9._%+-]+локальная часть до @
@разделитель
[a-zA-Z0-9.-]+домен
\.[a-zA-Z]{2,}точка и зона
СтрокаРезультат
user@example.comда
user@exampleнет (нет зоны)
bad @mail.comнет (пробел)
x@y.coда

Полные RFC-правила в regex не помещаются разумно — для UI достаточно упрощения; для почтового сервера — проверка доставкой.


Сквозной разбор — дата ДД-ММ-ГГГГ

^\d{2}-\d{2}-\d{4}$
ЧастьЗначение
\d&#123;2&#125;-\d&#123;2&#125;-\d&#123;4&#125;день, месяц, год с дефисами
^ $вся строка
СтрокаПодходит?
22-01-2026да
2-1-2026нет
32-01-2026да по regex, нет по календарю

Календарь (31.02) — в коде. Regex проверяет форму.

Год в двух цифрах (устаревший формат): ^\d&#123;2&#125;-\d&#123;2&#125;-\d&#123;2&#125;$ — осторожно с веком; лучше четыре цифры года.


Сквозной разбор — время ЧЧ:ММ:СС

^\d{2}:\d{2}:\d{2}$
СтрокаПо regexПо смыслу
14:30:05дада
25:00:00данет (часы)
9:05:01нетнужны ведущие нули 09:05:01

Строгая проверка часов 00-23 — отдельные классы или код:

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

(упрощённо, без учёта leap second).


Сквозной разбор — имя файла бэкапа

^data_\d{4}\.csv$

Подходит: data_2026.csv. Для поиска в списке файлов без привязки ко всей строке — уберите ^ $: data_\d{4}\.csv.


Сквозной разбор — путь

Unix-подобный файл:

^[A-Za-z0-9_./-]+$

Windows (без диска):

^[A-Za-z0-9_\\.\\-]+$

В реальных путях лучше pathlib / Path, а regex — для фильтра в логе ("похоже на .exe"):

\.exe$

Сквозной разбор — уровень в логе

2026-01-22 14:30:05 [ERROR] Connection timeout

Только слово ERROR в скобках:

\[ERROR\]
ЧастьЗначение
\[ \]буквальные скобки

Любой уровень — в Регулярные выражения — группы и замена: \[(INFO|WARN|ERROR)\]. Полная строка лога — в Регулярные выражения — рецепты и командная строка.


Сквозной разбор — номер заказа

Формат: ORD- + год + - + 4 цифры.

^ORD-\d{4}-\d{4}$
СтрокаРезультат
ORD-2026-0042да
ORD-26-42нет

Границы слова \b

Граница слова — переход между \w и "не \w" (пробел, знак препинания, начало/конец).

ШаблонТекстРезультат
catcategoryсовпадение внутри
\bcat\bcategoryнет
\bcat\ba cat.да

Для кириллицы \b ненадёжен — явные классы или lookaround из Регулярные выражения — проверки вокруг совпадения.


Альтернатива | — "или" (введение)

\b(ERROR|WARN|INFO)\b
ШаблонСмысл
`catdog`
`(Tt)he`
https?http или https (? у s, не |)

Скобки задают границы: one|two|three против one|(two|three).


Приоритет элементов

ШаблонЧитается как
ab+a + один и более b
(ab)+повторы пары ab
[a-z]+одна и более букв из класса
a{2,4}от 2 до 4 букв a

Квантификатор "липнет" к ближайшему слева элементу. Сомневаетесь — добавьте (...).


Unicode и национальные символы

[а-яА-ЯёЁ0-9_]+

JavaScript (флаг u):

/\p{L}+/u // буквы Unicode

Перед продакшеном — тест на реальных ФИО, адресах, логах.


Типичные ошибки на уровне синтаксиса

СимптомПричинаИсправление
Всё совпадает. вместо \.экранировать точку
"Пустой" match везде* допускает 0 раз+ или {1,}
Форма пропускает мусорнет $^...$
Находит внутри слованет \bграницы или якоря
Кириллица не ищется\w только ASCIIявный класс
В коде "не работает"забыли r"..."сырая строка

Упражнения (проверьте в лаборатории)

ЗадачаПодсказка
1Только цифры, 1–5 знаков^\d{1,5}$
2Слово error целиком\berror\b + флаг i
3Дата ГГГГ-ММ-ДДпоменять порядок блоков
4Файл .log в конце строки\.log$
5Текст до первого пробела[^\s]+

Шпаргалка шага 1

ЗадачаИдея шаблона
Точное словолитералы: error
"Что-то между"[^>]+ точнее, чем .*
Только цифры^\d+$
Дата ДД-ММ-ГГГГ^\d&#123;2&#125;-\d&#123;2&#125;-\d&#123;4&#125;$
Кусок до пробела[^\s]+
Время^\d&#123;2&#125;:\d&#123;2&#125;:\d&#123;2&#125;$

Потренируйтесь в лаборатории (пресеты Email и Дата). Готовые команды для терминала — Регулярные выражения — рецепты и командная строка.


Дальше: Группы и замена →

Содержание