Регулярные выражения — рецепты и командная строка
Предыдущие шаги: введение → синтаксис → группы → проверки → флаги.
Как пользоваться этой статьей
Каждый рецепт — стартовая точка, не промышленный стандарт. Перед продакшеном прогоните шаблон на своих данных в лаборатории, в готовых паттернах с разбором или на regex101.com с тем движком, который будете использовать (JavaScript, PCRE, .NET).
Формат разбора:
| Поле | Содержание |
|---|---|
| Шаблон | что вводить |
| Разбор | смысл блоков (см. синтаксис) |
| Пример текста | откуда копировать тест |
| Команда | grep, rg, PowerShell |
| Ограничения | когда regex лучше заменить кодом или парсером |
Если шаблон кажется магией — разберите его по синтаксису с нуля — якоря, классы, квантификаторы. Рецепт здесь — уже собранный конструктор.
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,} | зона |
Поиск всех адресов в абзаце — без ^ $:
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
| Тест | Ожидание |
|---|---|
user@example.com | да / найдено |
a@b.co | да |
user@.com | нет |
Команда:
rg -o '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' contacts.txt
-o — только совпавший фрагмент. Для UI-формы достаточно упрощения; доставка письмом — отдельная проверка.
Телефон +7 (Россия, гибко)
Поиск в тексте (скобки, пробелы, дефисы опциональны):
\+7\s?\(?\d{3}\)?\s?\d{3}[-\s]?\d{2}[-\s]?\d{2}
Строгий формат +7 916 555-12-34:
^\+7\s(\d{3})\s\d{3}-\d{2}-\d{2}$
| Группа | Поле |
|---|---|
| 1 | код оператора |
Пример текста:
Звоните +7 (916) 555-12-34 или +79165551234
Команда:
rg -o '\+7\s?\(?\d{3}\)?\s?\d{3}[-\s]?\d{2}[-\s]?\d{2}' page.html
Международные номера и внутренние добавочные — отдельные шаблоны или библиотека libphonenumber.
URL
https?://[^\s<>"']+
| Блок | Смысл |
|---|---|
https? | http или https |
:// | литерал |
[^\s<>"']+ | до пробела или кавычек |
Пример:
См. https://example.com/path?q=1 и http://test.local
Команда:
rg -o 'https?://[^[:space:]<>"']+' README.md
Query-параметры с & и кодировкой %20 шаблон обычно тянет; фрагмент #section — тоже. Проверка "живого" URL — HTTP-запросом, не regex.
Дата в разных форматах
Поиск в тексте (гибко):
\b\d{1,2}[./-]\d{1,2}[./-]\d{2,4}\b
Строго ДД-ММ-ГГГГ (форма):
^(?<day>\d{2})-(?<month>\d{2})-(?<year>\d{4})$
Именованные группы — Регулярные выражения — группы и замена. Замена в 22.01.2026: $<day>.$<month>.$<year> в .NET / VS Code.
ISO дата:
\b\d{4}-\d{2}-\d{2}\b
Команда — строки лога за 2026-01-22:
grep -E '^2026-01-22' application.log
rg '^2026-01-22' logs/
Время ISO 8601
\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?\b
| Блок | Смысл |
|---|---|
T | разделитель даты и времени |
(?:\.\d+)? | доли секунды |
(?:Z|...)? | UTC или смещение |
Пример: 2026-01-22T14:30:05.123Z
Команда:
rg '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}' events.jsonl
Строка лога (классический формат)
2026-01-22 14:30:05 [ERROR] Connection timeout host=10.0.0.5
Разбор всей строки:
^(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})\s+\[(\w+)\]\s+(.+)$
| Группа | Поле |
|---|---|
| 1 | дата |
| 2 | время |
| 3 | уровень |
| 4 | сообщение |
Только ERROR:
grep -E '\[ERROR\]' application.log
rg -n '\[ERROR\]' logs/
ERROR и WARN:
rg '\[(ERROR|WARN)\]' logs/
С контекстом (3 строки до и после):
grep -E -C 3 '\[ERROR\]' application.log
rg -C 3 '\[ERROR\]' logs/
Извлечь IP из хвоста (упрощённо):
host=(\d{1,3}(?:\.\d{1,3}){3})
Пресет Строка лога — в лаборатории.
Nginx / Apache
Nginx combined (фрагмент):
203.0.113.1 - - [22/Jan/2026:14:30:05 +0000] "GET /api HTTP/1.1" 500 1234
Код ответа 5xx:
" (5\d{2})
Команда:
rg '" (5\d{2}) ' /var/log/nginx/access.log
Полный разбор access.log — десятки полей; для аналитики часто берут awk или специализированные парсеры. Regex хорош для быстрого фильтра при инциденте. Типовые конфиги nginx и проверка curl — Nginx — конфиги под задачу.
IPv4 (черновик)
\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b
| Ограничение | Пояснение |
|---|---|
999.999.999.999 | пройдёт по regex, нет по смыслу |
CIDR 10.0.0.0/8 | нужен отдельный шаблон |
Строже октет 0–255 — уже в шаблоне через альтернативы; семантика сети — в коде.
Команда:
rg -o '\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b' dump.txt
Пресет IPv4 — лаборатория.
MAC-адрес
\b(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}\b
Пример: AA:BB:CC:DD:EE:FF, AA-BB-CC-DD-EE-FF
rg -i '[0-9A-Fa-f]{2}[:-](?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}' inventory.txt
UUID
\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b
Пример: 550e8400-e29b-41d4-a716-446655440000
rg -o '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}' traces.log
Версия и variant UUID — в коде, не в regex.
Семантическое версионирование (semver)
\b(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?\b
Примеры: 1.2.3, 2.0.0-beta.1, 1.0.0+build.42
rg 'v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)' CHANGELOG.md
Git commit (short hash)
\b[0-9a-f]{7,40}\b
Осторожно: совпадёт с любой hex-строкой нужной длины. Сузьте контекст:
\bcommit [0-9a-f]{7,40}\b
rg 'commit [0-9a-f]{7,40}' build.log
Хештег
#[\w\u0400-\u04FF]+
Примеры: #news, #новости
rg -o '#[\w\u0400-\u04FF]+' posts.txt
Серийный номер
\b[A-Z]{3}-\d{4}-[A-Z]{2}\b
Пример: ABC-2026-XZ
Для своего формата замените длины: [A-Z]{2,5}-\d{6,10}.
Повтор слова (опечатка)
\b(\w+)\s+\1\b
Пример: ошибка ошибка в тексте
rg '\b(\w+)\s+\1\b' draft.md
\1 — группы и замена. Для кириллицы замените \w+ на [а-яА-ЯёЁ\w]+.
JSON-поле (одна строка, упрощённо)
Значение "id": 123 или "id": "abc":
"id"\s*:\s*("([^"\\]|\\.)*"|\d+)
| Ограничение | Пояснение |
|---|---|
| Вложенный JSON | regex ломается |
| Многострочный pretty-print | нужен jq |
Надёжно:
jq '.id' response.json
Regex уместен для grep по логу, где JSON в одну строку:
rg '"level"\s*:\s*"ERROR"' api.jsonl
HTML-теги (грубо)
<[^>]+>
Удаление простых тегов без < внутри. Вложенная разметка — парсер DOM.
Атрибут href:
href="([^"]+)"
Группа 1 — URL в кавычках.
Ключ и значение в конфиге
# comment
db.host=127.0.0.1
db.port=5432
^([a-zA-Z0-9_.-]+)=(.*)$
Пропустить комментарии — проверки: ^(?!\s*#).
grep -E '^[a-zA-Z0-9_.-]+=.' app.conf
rg '^(?!\s*#)([a-zA-Z0-9_.-]+)=(.*)$' config/
CSV (одна строка без кавычек внутри полей)
^([^,]+),([^,]+),([^,]+)$
Три колонки. Реальный CSV с "поле, с запятой" — модуль csv в Python, не regex.
Кредитная карта (маскирование, не валидация)
Группы по 4 цифры:
\b(?:\d{4}[-\s]?){3}\d{4}\b
Огранение: не проверяет алгоритм Луна; для PCI — токенизация, не логирование полного номера. В логах ищут утечки маски:
rg '(?:\d{4}[-\s]?){3}\d{4}' *.log
Паспорт РФ (серия и номер, формат)
\b\d{4}\s?\d{6}\b
Пример: 4509 123456. Проверка контрольных цифр — в коде; regex — только формат в тексте.
Windows-путь в логе
[A-Za-z]:\\(?:[^\\\n]+\\)*[^\\\n]+
Пример: C:\Logs\app\error.log
Select-String -Path 'C:\logs\*.log' -Pattern '[A-Za-z]:\\[^\n]+'
Stack trace (Java, фрагмент)
^\s+at\s+[\w.$]+\([\w.]+\.java:\d+\)
Команда:
rg '^\s+at\s+' crash.txt
Командная строка — обзор
С нуля (что такое grep, findstr, Select-String, конвейеры) — поиск текста в файлах. Ниже — флаги и рецепты для тех, кто уже знаком с инструментами.
| Инструмент | ОС | Regex | Когда |
|---|---|---|---|
grep -E | Unix, Git Bash, WSL; Windows Preview — Microsoft Coreutils | ERE | один файл, фильтр |
rg | кроссплатформенно | Rust regex | дерево проекта |
sed -E | Unix | ERE | замена в файле |
awk | Unix | поля | фиксированные разделители |
findstr | Windows (CMD) | упрощённый | быстрый поиск |
| PowerShell | Windows | .NET | логи, скрипты |
Подробнее про терминал — раздел "Терминал" и поиск в файлах; про rg — продвинутый софт.
grep
| Задача | Команда |
|---|---|
| ERE | grep -E 'WARN|ERROR' file.log |
| Без учёта регистра | grep -Ei 'error' file.log |
| Номера строк | grep -En 'pattern' file.log |
| Обратный фильтр | grep -Ev 'DEBUG' file.log |
| Только совпадение | grep -Eo 'pattern' file.log |
| Контекст | grep -E -B2 -A5 'ERROR' file.log |
| Рекурсивно | grep -rE 'pattern' ./logs/ |
Без -E символы +, ?, |, {n} могут трактоваться как литералы (зависит от системы). На macOS BSD grep слабее GNU — предпочтительен rg или ggrep из Homebrew.
Подсчёт строк с ERROR:
grep -cE '\[ERROR\]' application.log
ripgrep (rg)
rg -n 'TODO|FIXME' --type py
rg -i 'connection timeout' .
rg --glob '*.log' '\[ERROR\]'
rg -l 'password\s*=' . # только имена файлов
rg -U 'BEGIN.*END' multiline.txt # многострочный режим
rg --replace '$2.$1.$3' -r '$3.$2.$1' -e '(\d{4})-(\d{2})-(\d{2})' dates.txt
| Флаг | Смысл |
|---|---|
-n | номер строки |
-i | без учёта регистра |
-l | только файлы |
-c | счётчик |
--glob | фильтр путей |
-U | . включает \n |
По умолчанию уважает .gitignore — удобно в репозитории.
sed
Замена первого вхождения в строке:
sed -E 's/(\d{4})-(\d{2})-(\d{2})/\3.\2.\1/' dates.txt
Все вхождения в строке (g):
sed -E 's/ERROR/WARN/g' app.log
На месте (бэкап на macOS — sed -i ''):
sed -E -i.bak 's/old/new/g' file.txt
Перед массовой правкой — копия файла и тест на фрагменте.
awk — поля по разделителю
awk '/\[ERROR\]/ { print $1, $2, $NF }' application.log
Третье поле времени, последнее — часто хвост сообщения (зависит от формата).
CSV (простой):
awk -F',' '{print $1, $3}' data.csv
Regex нужен, когда поля "плывут" или нужна маска внутри одного поля.
findstr (Windows)
findstr /R /C:"\[[Ee][Rr][Rr][Oo][Rr]\]" C:\logs\*.log
findstr /N /I "timeout" C:\logs\*.log
/R — regex (ограниченный). /N — номера строк. /I — регистр.
PowerShell (Windows)
Select-String -Path 'C:\logs\*.log' -Pattern '\[ERROR\]'
Get-Content 'C:\logs\app.log' | Select-String -Pattern 'host=(\d+\.\d+\.\d+\.\d+)'
Замена в строке:
'2026-01-22' -replace '(\d{4})-(\d{2})-(\d{2})', '$3.$2.$1'
Синтаксис групп — как в .NET (C#).
Bash — условие
if [[ $file =~ ^data_[0-9]{4}\.csv$ ]]; then
echo "Подходит под шаблон бэкапа"
fi
См. справочник Bash.
Perl one-liner (замена по stdin)
perl -pe 's/(\d{4})-(\d{2})-(\d{2})/$3.$2.$1/g' dates.txt
Полезно, когда sed ведёт себя по-разному на разных ОС, а Perl уже установлен.
Кейс — разбор инцидента за пять минут
Симптом: пользователи видят 500, в логе тысячи строк.
- Сузить файл и время:
rg '\[ERROR\]' logs/ --glob '*2026-01-22*'
- Вытащить уникальные сообщения:
rg -o '\[ERROR\]\s+\K.+' logs/app.log | sort | uniq -c | sort -rn | head
(\K в PCRE "сбрасывает" начало совпадения — в rg работает.)
- Найти IP или request id:
rg 'request_id=[a-f0-9-]+' logs/app.log
- Перейти в код по стабильной фразе из сообщения.
Regex здесь — скальпель, не замена мониторинга (Grafana, Sentry и т.д.).
Различия движков
| Возможность | JavaScript | .NET | Python re | grep -E | PCRE |
|---|---|---|---|---|---|
\d, \w | да | да | да | GNU да | да |
Именованные (?<n>…) | да | да | (?P<n>…) | редко | да |
| Lookbehind | да | да | да | ограниченно | да |
Флаг g | да | Matches | findall | — | — |
Ленивый *? | да | да | да | да | да |
\K | нет | нет | нет | нет | да (rg) |
| Таймаут | нет | MatchTimeout | нет (см. сторонние) | — | лимиты |
Всегда смотрите документацию своего инструмента. Шаблон с regex101 для PCRE может слегка отличаться в JavaScript.
Типичные ошибки новичка
| Ошибка | Что происходит | Что делать |
|---|---|---|
Забыли ^ $ в форме | xok проходит как email | якоря |
| Точка без экранирования | . = любой символ | \. |
Жадный .* | одно огромное совпадение | .*? или [^>]* |
\w для русского | кириллица выпадает | [а-яА-ЯёЁ] |
| Парсить JSON/HTML regex | ломается на вложенности | jq, DOM |
| Шаблон из интернета | ReDoS, сложность | упростить, тест |
| Двойные слэши в коде | \d → d | r"..." / @"..." |
grep без -E | | как литерал | grep -E или rg |
| Экранирование в shell | шаблон обрезан | одинарные кавычки '...' |
ReDoS — когда regex "зависает"
Шаблон (a+)+$ на длинной строке из a может считаться экспоненциально долго. В пользовательском вводе избегайте вложенных жадных + на повторяющихся группах. В .NET задайте MatchTimeout; подробнее — конечные автоматы.
Рабочий процесс
- Сформулировать задачу словами.
- Режим — поиск или вся строка (
^$для форм). - Собрать по Регулярные выражения — синтаксис с нуля; группы — Регулярные выражения — группы и замена; условия — Регулярные выражения — проверки вокруг совпадения; флаги — Регулярные выражения — флаги и жадность.
- Тест на реальных и "злых" строках.
- Лаборатория / regex101 с нужным движком.
- Перенос в код или CLI; в коде — комментарий к шаблону.
- Для ввода пользователя — лимит длины и таймаут.
Чек-лист перед продакшеном
| Вопрос | Действие |
|---|---|
| Валидация поля? | ^ и $ |
| Все вхождения? | g / findall / Matches |
| Кириллица? | проверить \w |
| Вложенные структуры? | парсер |
| Чужой шаблон? | упростить, нагрузочный тест |
| Логи в проде? | не хранить PII, найденные regex-ом |
Связь с разделом "Алгоритмы"
Регулярные выражения — сопоставление с регулярным языком (тип 3 в иерархии Хомского). Универсальный цикл программы — Алгоритм обработки.
Синтаксис по кирпичикам — Регулярные выражения — синтаксис с нуля. Введение и лаборатория — Регулярные выражения. Готовые шаблоны с кодом Python/JS — Regex — готовые паттерны.
← К оглавлению раздела "Регулярные выражения"
Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.