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

> Компактный язык шаблонов для поиска, проверки и замены текста; диалекты POSIX, PCRE, RE2, встроенные модули Python, JavaScript и Go, а также ловушки производительности (ReDoS).

Источник: https://llmdocs.ru/wiki/regex/ · обновлено 2026-11-09 · лицензия CC BY-SA 4.0

- **Основа**: регулярные языки (Клини, 1951–1956)
- **Первые реализации**: QED и ed (Кен Томпсон, 1968)
- **Диалекты**: POSIX BRE/ERE, PCRE/Perl, JavaScript, Python re, RE2
- **Движки**: обратный поиск (backtracking), автоматный (Thompson NFA/DFA)
- **Риск**: ReDoS — экспоненциальное время на «плохих» шаблонах
- **Инструменты**: grep, sed, ripgrep, regex101
**Регулярные выражения** (англ. *regular expressions*, regex) — компактный язык шаблонов для описания множеств строк. С их помощью ищут подстроки, проверяют формат ввода, извлекают части текста и выполняют замены. Регулярные выражения встроены почти во все языки программирования, редакторы и утилиты командной строки, от [grep](https://llmdocs.ru/wiki/grep.md) и [sed](https://llmdocs.ru/wiki/sed-awk.md) до IDE и СУБД.[1]

## История

Математик Стивен Клини в 1950-х описал **регулярные языки** и нотацию для них. Кен Томпсон в 1968 году реализовал её в редакторе QED, а затем в `ed`, откуда появился `grep` (*g/re/p* — «глобально найти регулярное выражение и напечатать»). Позднее POSIX стандартизировал базовый и расширенный синтаксис, а Perl в 1990-х добавил множество расширений; библиотека PCRE сделала этот диалект стандартом де-факто.

## Основной синтаксис

| Конструкция | Значение | Пример |
|---|---|---|
| `.` | любой символ (кроме перевода строки) | `a.c` → abc, a-c |
| `[abc]`, `[a-z]`, `[^0-9]` | класс символов, диапазон, отрицание | `[А-Яа-яЁё]` |
| `\d`, `\w`, `\s` | цифра, «словесный» символ, пробельный | `\d{3}` |
| `*`, `+`, `?` | 0 и больше, 1 и больше, 0 или 1 | `colou?r` |
| `{n}`, `{n,m}` | ровно n, от n до m повторений | `\d{2,4}` |
| `^`, `$` | начало и конец строки | `^#` |
| `\b` | граница слова | `\bcat\b` |
| `a\|b` | альтернатива | `jpe?g\|png` |
| `( )` | группа с захватом | `(\d+)-(\d+)` |
| `(?:...)` | группа без захвата | |
| `(?P<name>...)`, `(?<name>...)` | именованная группа | |
| `(?=...)`, `(?!...)`, `(?<=...)` | просмотр вперёд и назад | `\d+(?= ₽)` |

Квантификаторы по умолчанию **жадные** — захватывают как можно больше; `*?`, `+?` делают их ленивыми. Флаги меняют поведение: `i` — без учёта регистра, `m` — `^`/`$` для каждой строки, `s` — точка включает перевод строки, `x` — допускаются пробелы и комментарии в шаблоне.

## Примеры в языках

```python
import re

re.findall(r"\b\d{4}-\d{2}-\d{2}\b", "релизы 2024-05-01 и 2026-11-09")
# ['2024-05-01', '2026-11-09']

m = re.search(r"(?P<user>[\w.+-]+)@(?P<host>[\w.-]+)", "почта: ivan@example.com")
m.group("host")     # 'example.com'

re.sub(r"\s+", " ", "много   пробелов\n тут")   # 'много пробелов тут'
```

```javascript
const re = /(\d+)\s*₽/g;
[..."100 ₽ и 250₽".matchAll(re)].map(m => Number(m[1]));   // [100, 250]
```

```bash
grep -E '^(ERROR|WARN)' app.log
rg -o 'v\d+\.\d+\.\d+' CHANGELOG.md
```

В Python шаблоны пишут «сырыми» строками `r"..."`, чтобы обратные слеши не обрабатывались дважды; часто используемые выражения компилируют один раз через `re.compile`.

## Диалекты и движки

Синтаксис отличается в деталях: в POSIX BRE (`grep` без `-E`) скобки и `+` нужно экранировать, `\d` в POSIX отсутствует (вместо него `[[:digit:]]`), а просмотр назад и обратные ссылки поддерживаются не везде.

Важнее различие движков:[3]

- **Движки с обратным поиском** (backtracking) — Perl, PCRE, Python `re`, JavaScript, Java, .NET. Поддерживают обратные ссылки (`(\w)\1`) и просмотр, но на некоторых шаблонах работают экспоненциально долго.
- **Автоматные движки** (NFA/DFA по Томпсону) — RE2, пакет `regexp` в Go, крейт `regex` в Rust, ripgrep. Гарантируют время, линейное по длине входа, зато не поддерживают обратные ссылки и просмотр.[4]

## ReDoS

Шаблон с вложенными квантификаторами, например `^(a+)+$`, на строке `aaaaaaaaaaaaaaaaaaaaaaaa!` заставляет движок с обратным поиском перебрать экспоненциальное число вариантов. Если такой шаблон применяется к пользовательскому вводу, одна строка может занять процессор на минуты — это атака **ReDoS** (*regular expression denial of service*).[5] В июле 2019 года одно регулярное выражение в правилах WAF Cloudflare загрузило процессоры по всему миру и вызвало глобальный сбой на 27 минут.[6]

Защита: избегать вложенных и перекрывающихся квантификаторов (`(a|a)*`, `(.*)*`), ограничивать длину входа, задавать тайм-ауты, для недоверенных данных использовать линейные движки (RE2, Go, Rust), проверять шаблоны линтерами.

## Unicode

`\w` и `\d` в Python 3 по умолчанию понимают [Unicode](https://llmdocs.ru/wiki/unicode-utf8.md): `\d` совпадёт и с арабско-индийскими цифрами, поэтому для строгой проверки лучше `[0-9]` или флаг `re.ASCII`. В JavaScript для корректной работы с Unicode нужен флаг `u` (или `v`), тогда доступны классы вида `\p{L}` (любая буква) и `\p{Script=Cyrillic}`. Требования к Unicode-регулярным выражениям описывает стандарт UTS #18.[7]

## Когда не использовать

Регулярные выражения не умеют разбирать вложенные структуры произвольной глубины: HTML, JSON, языки программирования требуют настоящих парсеров. Для email и URL надёжнее библиотечные валидаторы и проверка подтверждением, чем «идеальная» регулярка на сотни символов. Длинные шаблоны стоит документировать флагом `x` и покрывать тестами; для отладки удобен сайт regex101, показывающий разбор и шаги движка. [Языковые модели](https://llmdocs.ru/wiki/llm.md) неплохо пишут и объясняют регулярные выражения, но их результат тоже нужно проверять на примерах.

## См. также

- [grep и регулярные выражения](https://llmdocs.ru/wiki/grep.md)
- [sed и awk](https://llmdocs.ru/wiki/sed-awk.md)
- [Unicode и UTF-8](https://llmdocs.ru/wiki/unicode-utf8.md)
- [Компилятор и интерпретатор](https://llmdocs.ru/wiki/compiler-interpreter.md)

## Источники

1. [Python — re: Regular expression operations](https://docs.python.org/3/library/re.html)
2. [MDN — Regular expressions (JavaScript)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions)
3. [Russ Cox — Regular Expression Matching Can Be Simple And Fast](https://swtch.com/~rsc/regexp/regexp1.html)
4. [RE2 syntax](https://github.com/google/re2/wiki/Syntax)
5. [OWASP — Regular expression Denial of Service (ReDoS)](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
6. [Cloudflare — Details of the Cloudflare outage on July 2, 2019](https://blog.cloudflare.com/details-of-the-cloudflare-outage-on-july-2-2019/)
7. [Unicode Technical Standard #18 — Unicode Regular Expressions](https://www.unicode.org/reports/tr18/)
