| 1 | <!-- kb_card |
| 2 | id: kb-regex-syntax-features-v1 |
| 3 | title: Regex — синтаксис и возможности (L1) |
| 4 | cluster: regex-friedl-mre3 |
| 5 | kb_layer: L1 |
| 6 | book_alignment: Блоки про метасимволы, квантификаторы, группы, утверждения — по логике части I–II MRE. |
| 7 | last_reviewed_utc: 2026-03-21 |
| 8 | --> |
| 9 | |
| 10 | # Regex: синтаксис и возможности (L1) |
| 11 | |
| 12 | ## Назначение |
| 13 | |
| 14 | Полное «лицевое» описание паттерна: из чего состоит выражение и как интерпретируются элементы в типичных NFA-диалектах (.NET, PCRE, Perl-стиль). |
| 15 | |
| 16 | ## Инварианты |
| 17 | |
| 18 | - Regex — **не** парсер произвольного HTML/JSON; для вложенных грамматик нужен другой инструмент. |
| 19 | - Семантика `\w`, `\b`, якорей и `.` **меняется** при Unicode- и многострочных опциях. |
| 20 | |
| 21 | <!-- section:literals-escaping --> |
| 22 | ## Литералы и экранирование |
| 23 | |
| 24 | - Литерал: символ без специального значения в данном диалекте. |
| 25 | - Экранирование: `\` перед метасимволом снимает спецсмысл; внутри `[...]` список «особых» символов другой (часто `- ] ^` требуют осторожности). |
| 26 | - В коде: различай **уровни** экранирования — строка языка → строка regex. |
| 27 | |
| 28 | **Практика:** в C# для сложных паттернов предпочтительны verbatim-строки `@"\d+"`, чтобы не раздувать `\\\\`. |
| 29 | <!-- /section:literals-escaping --> |
| 30 | |
| 31 | <!-- section:character-classes --> |
| 32 | ## Классы символов и отрицание |
| 33 | |
| 34 | - `[aeiou]` — один гласный. |
| 35 | - `[a-z]` — диапазон (зависит от локали/Unicode-режима). |
| 36 | - `[^0-9]` — один символ, не цифра. |
| 37 | - Встроенные классы POSIX (`[:alpha:]`) поддерживаются не везде. |
| 38 | |
| 39 | **Совет:** для «любой буквы» в Unicode-мире надёжнее `\p{L}` там, где доступны Unicode-категории (.NET, Java, PCRE с флагом). |
| 40 | <!-- /section:character-classes --> |
| 41 | |
| 42 | <!-- section:dot-and-modes --> |
| 43 | ## Точка и режимы строки |
| 44 | |
| 45 | - `.` — «почти любой символ»; перевод строки часто **исключён**, если не включён **однострочный** режим (`(?s)` в PCRE/.NET, флаги в JS). |
| 46 | - `^` и `$` — начало/конец **строки** или **всего текста** в зависимости от многострочного режима (`(?m)` и аналоги). |
| 47 | |
| 48 | Якоря «целого текста»: `\A` (начало входа), `\z` (конец), `\Z` (конец или перед финальным переводом строки) — где поддерживаются, дают более предсказуемое поведение, чем голый `$`. |
| 49 | <!-- /section:dot-and-modes --> |
| 50 | |
| 51 | <!-- section:quantifiers --> |
| 52 | ## Квантификаторы и жадность |
| 53 | |
| 54 | | Форма | Значение | |
| 55 | |-------|----------| |
| 56 | | `*` | 0 и более | |
| 57 | | `+` | 1 и более | |
| 58 | | `?` | 0 или 1 | |
| 59 | | `{n}` | ровно n | |
| 60 | | `{n,}` | не менее n | |
| 61 | | `{n,m}` | от n до m включительно | |
| 62 | |
| 63 | **Жадные** (по умолчанию): сначала максимизируют повтор, затем при неудаче **возвращают** (backtrack) шаг за шагом. |
| 64 | |
| 65 | **Ленивые** (`*?`, `+?`, `??`, `{m,n}?`): минимизируют локальное совпадение; всё равно могут вызывать много шагов backtracking на сложных паттернах. |
| 66 | |
| 67 | **Владение / атомарность** (где есть): блокируют откат внутри группы — см. `kb-regex-engines-efficiency-v1.md`. |
| 68 | <!-- /section:quantifiers --> |
| 69 | |
| 70 | <!-- section:grouping --> |
| 71 | ## Группировка, капчуры, ссылки |
| 72 | |
| 73 | - `( ... )` — нумерованная **захватывающая** группа. |
| 74 | - `(?: ... )` — **не** захватывает; уменьшает накладные расходы и удобна для OR внутри большого паттерна. |
| 75 | - `(?<name>...)` или `(?'name'...)` — именованная группа (.NET/PCRE). |
| 76 | - Обратные ссылки: `\1`, `\2` или `\k<name>` (синтаксис имён зависит от диалекта). |
| 77 | |
| 78 | **Важно:** нумерация групп учитывает порядок **открывающих** скобок; вложенность влияет на номера. |
| 79 | |
| 80 | **Условные группы** и **ветвления по предыдущему капчуру** — расширения PCRE/.NET; не переносить вслепую в минималистичные движки. |
| 81 | <!-- /section:grouping --> |
| 82 | |
| 83 | <!-- section:anchors-assertions --> |
| 84 | ## Якоря и утверждения нулевой ширины |
| 85 | |
| 86 | - `^`, `$` — см. режимы выше. |
| 87 | - `\b` — граница между «словесным» и несловесным символом; `\B` — не граница. |
| 88 | - **Lookahead:** `(?=...)` должно совпасть вперёд; `(?!...)` — не должно. |
| 89 | - **Lookbehind:** `(?<=...)`, `(?<!...)` — назад; в некоторых движках ограничены **фиксированной длиной**. |
| 90 | |
| 91 | Утверждения **не потребляют** символы входа: матч «на месте», удобно для проверок до/после без включения в результат. |
| 92 | |
| 93 | **Граничные случаи:** lookahead с квантификаторами на «.*» часто даёт неинтуитивный порядок из-за жадности и backtracking. |
| 94 | <!-- /section:anchors-assertions --> |
| 95 | |
| 96 | <!-- section:alternation --> |
| 97 | ## Альтернация и приоритет |
| 98 | |
| 99 | - `A|B` — сначала пробуется левая ветвь в типичном NFA; **порядок важен** для скорости и для того, какая ветвь «победит» при перекрывающихся совпадениях. |
| 100 | |
| 101 | Комбинируй с группами: `cat|dog` vs `^(cat|dog)$`. |
| 102 | <!-- /section:alternation --> |
| 103 | |
| 104 | ## Связи |
| 105 | |
| 106 | - `kb-regex-quickref-v1.md` |
| 107 | - `kb-regex-engines-efficiency-v1.md` |
| 108 | - `kb-regex-flavors-practice-v1.md` |
| 109 | - `regex-playbook.md` |
| 110 | |
| 111 | |