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

Регулярные выражения (англ. regular expressions, также regex или regexp)[1], иногда называемые также рациональными выражениями (англ. rational expressions)[2][3], — последовательности символов, задающие шаблон поиска в тексте. Обычно такие шаблоны применяются алгоритмами поиска строк для операций «найти» или «найти и заменить» в строках, а также для валидации ввода. Техника регулярных выражений разрабатывается в рамках теоретической информатики и теории формальных языков.

Понятие регулярных выражений было формализовано в 1950-х годах американским математиком Стивен Коул Клин при описании регулярных языков. Интенсивное распространение регулярных выражений произошло с внедрением текстовых утилит UNIX. С 1980-х годов появились различные синтаксисы записи регулярных выражений, в частности стандарты POSIX и синтаксис Perl.

Регулярные выражения используются в поисковых системах, диалогах поиска и замены текстовых редакторов и процессоров, в утилитах обработки текста (таких, как sed и AWK), а также при лексическом анализе. В большинстве языков программирования поддержка регулярных выражений реализована как библиотеки, которые часто называют «движками»[4], причём доступны десятки различных реализаций. В сфере генеративного искусственного интеллекта и больших языковых моделей (LLM) регулярные выражения применяются в механизмах ограниченного декодирования (англ. constrained decoding) для обеспечения структурной целостности ответов[5][6].

История

undefined

Регулярные выражения появились в 1951 году, когда математик Стивен Коул Клин описал регулярные языки через математическую нотацию, которую назвал «регулярными событиями» (англ. regular events)[7]. Формализм возник в рамках теории автоматов и описания формальных языков, с первоначальной целью описания архитектуры ранних искусственных нейронных сетей. (Клин изначально назвал эти события «prehensible» в противопоставление модели МакКаллока — Питтса, позднее признав: «Мы будем рады любым предложениям, как сделать термин более описательным.») В ранних языках программирования, таких как SNOBOL, использовались другие формализмы поиска по шаблону.

Практическое применение регулярных выражений началось в 1968 году: с одной стороны, для поиска по паттернам в текстовом редакторе[8] — благодаря инициативе Кена Томпсона по интеграции нотации Клина в редактор QED — а с другой стороны, для лексического анализа в компиляторах[9]. Томпсон реализовал сопоставление с помощью JIT-компиляции в байт-код для IBM 7094 на раннем CTSS — это один из первых примеров JIT-подхода. Позже этот подход появился и в редакторе ed (UNIX), что привело к появлению инструмента grep, название которого образовано от команды поиска по регулярному выражению: g/re/p («Global search for Regular Expression and Print matching lines»)[10]. В этот же период группа Д. Т. Росса реализовала на основе идей Клина инструменты для лексического анализа в компиляторах.

В 1970-х в Bell Labs на базе Unix создавались многочисленные вариации регулярных выражений: lex, sed, AWK, expr, а также редакторы vi и Emacs, в последнем реализован собственный несовместимый синтаксис[11]. Эти ранние формализмы были стандартизированы в POSIX.2 (1992).

В 1980-х новый этап развития ознаменовался появлением Perl и библиотеки регулярных выражений Генри Спенсера (1986), которую адаптировали для Tcl («Advanced Regular Expressions»)[12]. Реализация Tcl представляет собой гибрид НКА/ДКА с улучшенной производительностью и применяется, например, в PostgreSQL[13]. Perl расширил возможности за счёт новых конструкций[14]. Особое развитие получила интеграция с Raku (Perl 6), которая оформилась в мини-язык «Raku rules» для описания грамматик и поддержала BNF-стиль задания рекурсивных спусков.

Регулярные выражения легли в основу формализации грамматик описания структуры документов и баз данных в промышленных стандартах 1980-х, включая ISO SGML, DTD и последующие спецификации XML.

Сегодня регулярные выражения встроены во многие языки программирования (Java, Python, Perl, ECMAScript и др.), используются в программах для работы с текстом, анализаторах лексем, редакторах и других утилитах. Современные реализации используют аппаратные ускорители на базе FPGA и GPU[15] для ускорения обработки по сравнению с реализацией на CPU.

В период 2020–2025 годов аппаратное ускорение на базе ПЛИС (FPGA) получило развитие в системах глубокого анализа пакетов (DPI) и обнаружения вторжений (IDS/IPS). Аппаратный параллелизм применяется для высокоскоростного сопоставления с шаблонами в реальном времени, обеспечивая фильтрацию трафика с высокой пропускной способностью и низкими задержками, в том числе при интеграции с алгоритмами искусственного интеллекта для сетей 5G. Также в эти годы активно развивался стандарт ECMAScript (ES2020–ES2025), в который были добавлены новые возможности для работы с регулярными выражениями, включая методы глобального поиска и замены, улучшенную поддержку Юникода, локальные модификаторы шаблонов и встроенное экранирование строк[16][17][18].

Паттерны

Термин англ. regular expressions (регулярные выражения) либо англ. regexes (регексы) часто относится к конкретному стандартному синтаксису записи шаблонов поиска текста, отличному от исходной математической нотации. Каждый символ в регулярном выражении либо является метасимволом (обозначает особое действие), либо обычным (сопоставляется буквально). Например, в выражении b. латинская «b» — литерал, а точка — метасимвол (соответствует любому символу, кроме перевода строки). Метасимволы и литералы используются для описания классов текстов или наборов совпадающих строк.

Пример: seriali[sz]e находит оба варианта написания слова: «serialise» и «serialize». Шаблонные символы (wildcards) реализуют похожие функции, но в более ограниченном виде.

Глоббинг файлов в списках файлов применяет шаблоны с подстановочными знаками, но регулярные выражения обычно используются для анализа строк в общем виде. Пример: ^[ \t]+|[ \t]+$ — для поиска лишних пробелов в начале или конце строк. Более сложный шаблон для чисел: [+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?.

undefined

Движок регулярных выражений преобразует заданный паттерн в внутреннее представление и сравнивает его с целевым текстом. Один из подходов — алгоритм Томпсона (Thompson's construction) — строит НКА, затем приводит его к ДКА и запускает для поиска совпадений.

Базовые конструкции

Регулярное выражение (шаблон) задаёт множество строк. Для конечного множества можно просто перечислить все элементы, но зачастую регулярное выражение позволяет задать множество компактно. Например, паттерн H(ä|ae?)ndel соответствует «Handel», «Händel», «Haendel»; иной вариант — (Hän|Han|Haen)del.

Основные операции для построения регулярных выражений:

Логическое «или»
Вертикальная черта («|») разделяет альтернативы. Пример: gray|grey.
Группировка
Скобки — задают область действия операторов. Например, gr(a|e)y и gray|grey эквивалентны.
Квантификация
Квантификатор после элемента (литерала, группы) задаёт число повторений: «?» (ноль или одно), «*» (звезда Клини — от нуля до бесконечности), «+» (плюс Клини — одно и более раз).
? Вопросительный знак означает «ноль или одно вхождение». Пример: colou?r находит “color” и “colour”.
* Звёздочка означает «ноль или более». Пример: ab*c — "ac", "abc", "abbc", и т. д.
+ Плюс — «одно или более». Пример: ab+c — "abc", "abbc", "abbbc", но не "ac".
{n}[19] Предыдущий элемент повторяется ровно n раз.
{min,}[19] От min раз и более.
{,max}[19] До max раз максимум.
{min,max}[19] Не менее min, не более max раз.
Подстановочный символ
Точка (.) соответствует любому символу. Примеры:
a.b — "a%b", "axb", "a5b", и т. п.
a.*b — все строки, где после «a» где-то позже встречается «b».

Эти конструкции комбинируются для построения любых выражений.

Точный синтаксис зависит от конкретной реализации — см. ниже раздел «Синтаксис».

Теория формальных языков

Регулярные выражения описывают регулярные языки в теории формальных языков и эквивалентны регулярным грамматикам. Язык самих регулярных выражений — контекстно-свободный язык.

Формальное определение

Регулярные выражения строятся из констант, обозначающих множества строк, и операторов, обозначающих операции над ними. Пусть Σ — конечный алфавит. Стандартные константы:

  • (пустое множество) ∅ — пустое множество ∅.
  • (пустая строка) ε — множество из единственной пустой строки.
  • (литерал) a ∈ Σ — множество, состоящее из строки-литерала.

Далее над ними определяют операции:

  • Конкатенация (RS) — все строки, получаемые склеиванием строки из R и строки из S.
  • Альтернатива (R|S) — объединение множеств R и S.
  • Звезда Клини (R*) — наименьшее надмножество множества R, содержащее ε и замкнутое относительно конкатенации (любое количество повторений элементов R, в том числе ноль).

Приоритет: звезда Клини > конкатенация > альтернатива. Круглые скобки можно опускать в случае однозначности. Для альтернативы иногда используют ∪, + или ∨.

Примеры

  • [hc]?at — «at», «hat», «cat»
  • [hc]*at — все слова, где перед «at» любая последовательность «h», «c»
  • cat|dog — «cat» или «dog»

Выразительность и лаконичность

Формальное определение минимально по набору операций: ? и + выражаются через базовые — a+ = aa*, a? = (a|ε). Иногда вводят оператор дополнения для краткости (все строки, не входящие в заданное регулярное выражение), но выразительную силу это не увеличивает, лишь сокращает запись[20][21].

Регулярные выражения строго описывают класс языков, распознаваемых детерминированными конечными автоматами, однако в ряде случаев DFA требует экспоненциально большего числа состояний по сравнению с коротким выражением (пример: язык всех слов, в которых k-я с конца буква — «a»). Для преобразования регулярного выражения в НКА используют алгоритм Томпсона, для обратного преобразования — алгоритм Клина.

Отметим, что «реальные» движки регулярных выражений часто реализуют возможности, выходящие за пределы регулярных языков.

Эквивалентность выражений

Операции над регулярными выражениями (например, перестановка местами альтернатив, скобочное вложение) могут приводить к эквивалентным языкам — существуют алгоритмы проверки эквивалентности, основанные на приведении к минимальному ДКА[22].

Синтаксис

Регулярное выражение (паттерн) состоит из последовательности атомов; атому сопоставляется подстрока строки. Атомом чаще всего является литерал, но могут быть использованы скобки для группировки, повторения, альтернативы и обратные ссылки (backreferences). Совпадение считается, если все атомы паттерна найдены.

В зависимости от реализации, насчитывается свыше десятка метасимволов: { } [ ] ( ) ^ $.|*+? и \\; для обозначения буквального символа используются экранирования. В современных движках (например, PCRE2) количество метасимволов значительно превышает десяток, и в базовый набор включены символы свойств Unicode (\\p, \\P)[23][24].

Разделители

В языках программирования регулярные выражения часто помещают в строковые литералы; в некоторых случаях (например, Perl) паттерн выделяют косыми чертами: /re/. Альтернативные разделители иногда удобны для избежания экранирования символов-разделителей внутри паттерна.

Стандарт POSIX

POSIX определяет режимы BRE (Basic Regular Expressions), ERE (Extended Regular Expressions) и устаревший SRE (deprecated). BRE требует экранирования некоторых скобок и фигурных скобок, ERE — нет, и добавляет операторы ?, +, |. Например, в GNU grep ERE вызывается через -E, BRE — через -G; -P включает синтаксис Perl.

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

POSIX (основной/расширенный)

В режиме BRE скобки и фигурные скобки обозначаются как \(\), \{\}, в ERE — как (), {}. Таблица основных метасимволов:

Метасимвол Описание
^ Начало строки (или строки, если поиск посрочный)
. Любой одиночный символ (кроме перевода строки)
[ ] Набор разрешённых символов; [abc] — «a»/«b»/«c»; диапазоны [a-z]; минус в начале/конце — литерал.
[^ ] Любой символ, кроме перечисленных
$ Конец строки (или строки)
( ) Группировка (каптуринг-группа); в BRE \(\)
\n Ссылка на n-ю группу (backreference)
* Ноль или более повторений
{m,n} Не менее m, не более n раз

Метасимволы в ERE

В ERE экранирование инвертирует смысл ряда метасимволов. В ERE — (), {}, backreferences нет.

Метасимвол Описание
? Ноль или одно вхождение
+ Одно или более
Альтернатива

Классы символов

Класс символов — основная конструкция для сопоставления с набором символов, например [A-Z] — любая заглавная латинская; \d — любая цифра.

Описание POSIX Perl/Tcl Vim Java ASCII
Латиница, цифры, _ [:alnum:] \w \w \w [A-Za-z0-9_]
Пробел/табуляция [:blank:] \s \p{Blank} [ \t]
Граница слова \b \b (?<=\W)(?=\w)|(?<=\w)(?=\W)
Цифра [:digit:] \d \d \d [0-9]

POSIX-классы могут использоваться только внутри конструкций [...].

Perl и PCRE

Perl и совместимые синтаксисы (PCRE) расширяют набор атомов и модификаторов: группы, Backreferences, ленивые квантификаторы, именованные группы, рекурсии. широкий набор подобных поддерживается в Java, Python, JavaScript и других языках[25].

PCRE2 (Perl Compatible Regular Expressions) — широко используемая C-библиотека и современное развитие PCRE, лежащая в основе работы регулярных выражений во многих языках и инструментах, включая PHP и R[26]. В 2024 году в неё были внесены значительные обновления[27]:

  • Поддержка стандарта Unicode была обновлена до версий 15.1, 16.0 и 17.0 (начиная с версии библиотеки 10.48)[28].
  • Добавлена поддержка утверждений просмотра назад (lookbehind) с ограниченной переменной длиной[27].
  • Изменено поведение квантификаторов вида {,n} (например, {,3}), которые теперь трактуются как {0,n} для совместимости с Perl[27].
  • Введены новые функции API, такие как pcre2_get_match_data_heapframes_size() для контроля над памятью и pcre2_next_match() для безопасного перебора совпадений[27].

ECMAScript (JavaScript)

Стандарт ECMAScript, на котором основан JavaScript, получил значительные обновления для регулярных выражений в версиях ES2024 и ES2025. Развитие стандарта продолжается: на стадии рассмотрения находятся предложения для ES2026 (например, RegExp.escape и RegExp Buffer Boundaries), а также флаг x (IgnorePatternWhitespace) для игнорирования неэкранированных пробелов[29][30][31].

ES2024

Ключевым нововведением стандарта ES2024 стал флаг v, который является усовершенствованной версией флага u (для полной поддержки Unicode). Новый флаг добавил возможность выполнять операции над наборами символов, такие как вычитание и пересечение, а также поддержку свойств Unicode для многосимвольных строк[32]. Примеры синтаксиса для операций над множествами внутри символьных классов:

  • Вычитание: [\p{Script_Extensions=Greek}--π] (соответствует всем греческим символам, кроме «π»)[33];
  • Пересечение: [\p{Script_Extensions=Greek}&&\p{Letter}] (соответствует символам, которые присутствуют одновременно в обоих наборах)[33].

ES2025

Для стандарта ES2025 были финализированы (достигли стадии 4) следующие возможности:

  • Модификаторы шаблона (англ. Pattern Modifiers): введён синтаксис, позволяющий включать или отключать флаги для отдельных частей регулярного выражения, а не для всего шаблона целиком. Поддерживаются флаги i, m и s, допускается их отключение (например, (?-i:...)) и вложенность. Например, конструкция (?i:subpattern) применяет регистронезависимый поиск только к подшаблону subpattern[34][35].
  • RegExp.escape(): добавлен встроенный статический метод для экранирования специальных символов в строке (среди них ^, $, \, ., *, +, ?, скобки и другие). Это позволяет безопасно создавать регулярные выражения из пользовательского ввода или других переменных, снижая риск ошибок и устраняя необходимость в самописных функциях экранирования[34][36].
  • Дублирующиеся имена для групп захвата: разрешено использовать одинаковые имена для групп захвата в разных ветвях альтернативного сопоставления (например, при использовании оператора |). Данное расширение синтаксиса допустимо при условии, что в ходе сопоставления может сработать только одна из групп с одинаковым именем; при использовании обратных ссылок \\k<name> ссылка указывает на ту группу, которая фактически участвовала в сопоставлении[37][38].

Ленивое сопоставление

Во многих интерпретациях (Python, Java) квантификаторы по умолчанию жадные, то есть поглощают максимум символов[39]. Для ленивого (минимального) поведения используется суффикс ?: ".+?".

Посессивные квантификаторы

В некоторых реализациях (например, Java, Python 3.11+) квантификаторы могут быть посессивными (жадность без бэктрекинга), отмечается как *+ и т. п[40].

IETF I-Regexp

IETF RFC 9485 описывает унифицированный подмножество регулярных выражений («I-Regexp»), обеспечивающий кроссплатформенную переносимость сопоставления без дополнительных расширений[41].

Нерегулярные расширения

Современные движки поддерживают конструкции, выходящие за пределы регулярных языков: например, backreferences позволяют сопоставлять шаблоны типа "papa", "WikiWiki", то есть повторяющиеся группы ((.+)\1), что формально неописуемо в терминах регулярных грамматик.

Использование backreferences делает задачу сопоставления NP-полной[42].

Тем не менее, термин «регулярные выражения» распространён для их описания и за пределами формальных регулярных языков. В таких случаях для механизма часто используют слово «регексы» или «паттерны».

Современный синтаксис также поддерживает именованные группы захвата, которые записываются как (?<name>...). Для обращения к таким группам внутри шаблона используются именованные обратные ссылки, например, \k<name> (в PCRE2 также поддерживаются варианты \g{name}, (?P=name))[43][44].

Ассерции (утверждения)

Расширенные регулярные выражения поддерживают lookahead и lookbehind-утверждения для сложных видов поиска: (?=...), (?!...), (?<=...), (?<!...). Они широко используются с 1990-х (начиная с Perl 5)[45].

Реализации и производительность

Существуют три базовых класса алгоритмов проверки соответствия строки регулярному выражению:

  • неявное построение ДКА (O(2^m), использование памяти экспоненциально по размеру выражения, поиск — линейный по длине строки)
  • моделирование НКА (O(mn)), используется в большинстве стандартных реализаций
  • бэктрекинг (экспоненциальное время в некоторых случаях из-за возвратов; может привести к уязвимости ReDoS)

Описаны ускоренные варианты (Boyer—Moore и др.), а также теоретические подходы с уменьшением экспоненты[46].

Также применяется механизм «ленивого ДКА» (Lazy DFA), который кэширует состояния «на лету» для избежания экспоненциального взрыва памяти при сохранении линейного времени поиска. Этот подход используется в таких движках, как RE2 и Rust regex[47]

Среди доминирующих современных движков выделяются:

  • Google RE2 и Rust regex — ориентированы на безопасность и гарантированное линейное время выполнения, не поддерживают обратные ссылки[48]
  • PCRE2 — отличается полнотой синтаксиса (поддерживает сложные конструкции, включая обратные ссылки), однако подвержен катастрофическому возврату[48]

Защита от уязвимостей (ReDoS)

Современные методы защиты от ReDoS включают внедрение альтернативных алгоритмов сопоставления и механизмов ограничения времени выполнения. В движок V8 (начиная с версии 8.8) был добавлен не-бэктрекинговый алгоритм, гарантирующий линейное время выполнения. В платформе .NET аналогичный не-бэктрекинговый движок появился в версии 7, а начиная с версии 4.5 разработчикам доступно использование таймаутов для ограничения времени выполнения регулярных выражений. При использовании неподдерживаемых функций (например, обратных ссылок) безопасные движки ведут себя по-разному: V8 автоматически возвращается к стандартному уязвимому алгоритму с возвратом, тогда как .NET выдаёт ошибку. Уязвимости типа ReDoS обнаруживаются и в популярных библиотеках: например, они были найдены в пакетах cross-spawn и micromatch, после чего были исправлены в новых версиях.

Unicode

Регулярные выражения могут работать с любыми токенами, но классически основывались на ASCII. Современные движки поддерживают Unicode, что порождает особенности:

  • поддержка разных кодировок (UTF-8, UTF-16, UTF-32)
  • диапазон поддерживаемых символов (только BMP или весь Unicode)
  • расширение классических описаний [x-y] на диапазоны кодовых точек Unicode; ограничения по пересечению блоков (Vim, gawk)
  • флаги регистронезависимости — для ASCII, для Unicode
  • дополнительные классы — для блоков, скриптов, свойств символов
  • вопросы нормализации: эквивалентность канонических и составных символов
  • поддержка контрольных и управляющих символов (BOM)

Поддержка Unicode постоянно совершенствуется. Например, библиотеки PCRE2 и ICU поддерживают стандарты Unicode вплоть до версии 17.0[49][50]. В стандарте ECMAScript 2024 был введён флаг v, который является усовершенствованной версией флага u (Unicode) и добавляет операции над наборами символов (вычитание, пересечение), а также поддержку свойств Unicode для многосимвольных строк.

Поддержка языками программирования

Большинство языков общего назначения содержит либо встроенную поддержку регулярных выражений, либо библиотеки с их реализацией. В платформе .NET опция RegexOptions.ECMAScript приближает поведение регулярных выражений к JavaScript, но не поддерживает современные флаги u и v, из-за чего возникают расхождения в обработке астральных символов и Unicode-свойств[51].

Применение

Регулярные выражения широко используются при обработке текста: валидация данных, скрейпинг данных, парсинг, подсветка синтаксиса, форматирование. В настольных издательских системах регексы могут использоваться для массового применения стилей к тексту (например, для выделения слов из заглавных букв). Использование в публичных поисковых системах обычно не предоставляется из-за ресурсоёмкости; исключения — Google Code Search (закрыт в 2012), Exalead[52]. В сфере больших языковых моделей (LLM) и генеративного ИИ регулярные выражения применяются для механизмов ограниченного декодирования (англ. constrained decoding / JSON mode), обеспечивая структурную целостность генерируемых токенов[6].[53]

Примеры

Конкретный синтаксис зависит от реализации, языка или библиотеки. Отличия могут касаться типа скобок, модификаторов (жадный/ленивый), наличия дополнительных классов символов. Обычно используется синтаксис Perl (PCRE).

Примерная таблица основных конструкций:

Метасимвол Описание Пример (Perl)
. Любой символ, кроме перевода строки
$string1 = "Hello World\n";
if ($string1 =~ m/...../) {
  print "$string1 has length >= 5.\n";
}
() Группировка; доступ к содержимому через $1, $2 и т. д.
$string1 = "Hello World\n";
if ($string1 =~ m/(H..).(o..)/) {
  print "We matched '$1' and '$2'.\n";
}
+ Один или более раз
$string1 = "Hello World\n";
if ($string1 =~ m/l+/) {
  print "There are one or more consecutive letter \"l\"'s in $string1.\n";
}
? Ноль или один раз
$string1 = "Hello World\n";
if ($string1 =~ m/H.?e/) {
  print "Есть 'H' и 'e' с 0–1 символами между ними (например, He Hue Hee).\n";
}
? Ленивый модификатор
$string1 = "Hello World\n";
if ($string1 =~ m/(l.+?o)/) {
  print "Ленивое сопоставление: 'llo', а не 'llo Wo'.\n";
}
* Ноль или более раз
$string1 = "Hello World\n";
if ($string1 =~ m/el*o/) {
  print "Е есть 'e', 0+ букв 'l', далее 'o' (eo, elo, ello, elllo).\n";
}
{M,N} От M до N раз (в том числе одно из крайних значений)
$string1 = "Hello World\n";
if ($string1 =~ m/l{1,2}/) {
  print "Есть подстрока из 1–2 букв 'l'.\n";
}
[…] Один из символов
$string1 = "Hello World\n";
if ($string1 =~ m/[aeiou]+/) {
  print "$string1 contains one or more vowels.\n";
}
Альтернатива
$string1 = "Hello World\n";
if ($string1 =~ m/(Hello|Hi|Pogo)/) {
  print "$string1 содержит одно из Hello, Hi или Pogo";
}
\b Граница слова
$string1 = "Hello World\n";
if ($string1 =~ m/llo\b/) {
  print "Слово заканчивается на 'llo'.\n";
}
\w Буквенно-цифровой символ (латиница, цифры, _)
$string1 = "Hello World\n";
if ($string1 =~ m/\w/) {
  print "Есть хотя бы один буквенно-цифровой символ.\n";
}
\W Не буквенно-цифровой символ
$string1 = "Hello World\n";
if ($string1 =~ m/\W/) {
  print "Пробел между Hello и World — не алфавитно-цифровой.\n";
}
\s Пробельный символ (в том числе табуляция, перевод строки)
$string1 = "Hello World\n";
if ($string1 =~ m/\s.*\s/) {
  print "В строке есть >1 пробельных символа.\n";
}
\S Любой символ, кроме пробельных
$string1 = "Hello World\n";
if ($string1 =~ m/\S.*\S/) {
  print "Есть два непустых символа, разделённых чем угодно.\n";
}
\d Цифра
$string1 = "99 bottles of beer on the wall.";
if ($string1 =~ m/(\d+)/) {
  print "$1 — первое число в '$string1'\n";
}
\D Нецифра
$string1 = "Hello World\n";
if ($string1 =~ m/\D/) {
  print "Хотя бы один символ не является цифрой.\n";
}
^ Начало строки
$string1 = "Hello World\n";
if ($string1 =~ m/^He/) {
  print "Строка начинается с 'He'.\n";
}
$ Конец строки
$string1 = "Hello World\n";
if ($string1 =~ m/rld$/) {
  print "Строка заканчивается на 'rld'.\n";
}

Индукция

Регулярные выражения могут выводиться («индуцироваться») автоматически по набору примеров строк (вычислительное обучение грамматик). Такие методы позволяют строить паттерны по положительным и отрицательным примерам.

Примечания

  1. Goyvaerts, Jan Regular Expression Tutorial - Learn How to Use Regular Expressions. Regular-Expressions.info. Дата обращения: 27 августа 2026. Архивировано 1 ноября 2016 года.
  2. Mitkov, Ruslan. The Oxford Handbook of Computational Linguistics. — Oxford University Press, 2003. — P. 754. — ISBN 978-0-19-927634-9.
  3. Lawson, Mark V. Finite Automata. — CRC Press, 17 сентября 2003. — P. 98–100. — ISBN 978-1-58488-255-8.
  4. How a Regex Engine Works Internally. regular-expressions.info. Дата обращения: 27 августа 2026. Архивировано 16 августа 2003 года.
  5. LLM Structured Output in 2026: Stop Parsing JSON with Regex and Do It Right. dev.to. Дата обращения: 27 августа 2026.
  6. 1 2 Aidan Cooper. Constrained Decoding: How to Force LLMs to Output Valid JSON, XML, or Regex. aidancooper.co.uk (15 мая 2024). Дата обращения: 27 августа 2026.
  7. Leung, Hing Regular Languages and Finite Automata. New Mexico State University (16 сентября 2010). — «The concept of regular events was introduced by Kleene via the definition of regular expressions.» Дата обращения: 27 августа 2026. Архивировано 5 декабря 2013 года.
  8. Kernighan, Brian. A Regular Expressions Matcher // Beautiful Code. — O'Reilly Media, 8 августа 2007. — P. 1–2. — ISBN 978-0-596-51004-6.
  9. Ritchie, Dennis M. An incomplete history of the QED Text Editor. Дата обращения: 9 октября 2013. Архивировано 21 февраля 1999 года.
  10. Raymond, Eric S. (по воспоминаниям Денниса Ритчи). Jargon File 4.4.7: grep (2003). Дата обращения: 27 августа 2026. Архивировано 5 июня 2011 года.
  11. Aho, Alfred V. Chapter 10. Patterns, Automata, and Regular Expressions // Foundations of Computer Science / Alfred V. Aho, Jeffrey D. Ullman. — 1992.
  12. New Regular Expression Features in Tcl 8.1. Дата обращения: 11 октября 2013. Архивировано 7 октября 2020 года.
  13. Documentation: 9.3: Pattern Matching. PostgreSQL. Дата обращения: 27 августа 2026. Архивировано 7 октября 2020 года.
  14. Wall, Larry. Perl Regular Expressions. perlre (2006). Дата обращения: 27 августа 2026. Архивировано 31 декабря 2009 года.
  15. CUDA grep. bkase.github.io. Дата обращения: 27 августа 2026. Архивировано 7 октября 2020 года.
  16. Regex стала лучше: история и будущее регулярных выражений в JavaScript. msiter.ru. Дата обращения: 27 августа 2026.
  17. Что нового в ECMAScript 2025. Tproger. Дата обращения: 27 августа 2026.
  18. ECMAScript 2025 JavaScript standard takes shape. InfoWorld. Дата обращения: 27 августа 2026.
  19. 1 2 3 4 Kerrisk, Michael grep(1) - Linux manual page. man7.org. Дата обращения: 27 августа 2026. Архивировано 12 октября 2025 года.
  20. Gelade & Neven (2008, p. 332, Thm.4.1)
  21. Gruber & Holzer (2008)
  22. Hopcroft, John E. Introduction to Automata Theory, Languages, and Computation / John E. Hopcroft, Rajeev Motwani, Jeffrey D. Ullman. — Upper Saddle River, New Jersey : Addison Wesley, 2003. — P. 117–120. — ISBN 978-0-201-44124-6.
  23. PCRE2 - New Syntax. PCRE2 Project. Дата обращения: 27 августа 2026.
  24. PCRE2 - Pattern Matching Syntax. PCRE2 Project. Дата обращения: 27 августа 2026.
  25. Perl Regular Expression Documentation. perldoc.perl.org. Дата обращения: 27 августа 2026. Архивировано 31 декабря 2009 года.
  26. PCRE2 - Perl-compatible regular expressions. pcre2project.github.io. Дата обращения: 27 августа 2026. Архивировано 15 сентября 2025 года.
  27. 1 2 3 4 NEWS - platform/external/pcre - Git at Google. android.googlesource.com. Дата обращения: 27 августа 2026.
  28. NEWS. PCRE2 Project on GitHub. PCRE2Project. Дата обращения: 27 августа 2026.
  29. TC39 Advances 3 Proposals to Stage 4: RegExp.escape, Float16Array, and Redeclarable Global Eval. Socket Blog (18 февраля 2025). Дата обращения: 27 августа 2026.
  30. TC39 Proposals. GitHub. TC39. Дата обращения: 27 августа 2026.
  31. proposal-regexp-x-mode. GitHub. TC39. Дата обращения: 27 августа 2026.
  32. The History (And Future) Of Regular Expressions In JavaScript. Smashing Magazine. Дата обращения: 27 августа 2026. Архивировано 9 сентября 2025 года.
  33. 1 2 Regular Expression v Flag. V8.dev. Дата обращения: 27 августа 2026.
  34. 1 2 ECMAScript 2025 Language Specification. tc39.es. Дата обращения: 27 августа 2026.
  35. Regular expression modifier. MDN Web Docs. Дата обращения: 27 августа 2026.
  36. RegExp.escape(). MDN Web Docs. Дата обращения: 27 августа 2026.
  37. Proposal: Duplicate Named Capturing Groups. GitHub. TC39. Дата обращения: 27 августа 2026.
  38. Backreferences to Duplicate Named Capture Groups. Regular-Expressions.info. Дата обращения: 27 августа 2026.
  39. Regular Expression Syntax. Python 3.5.0 documentation. Python Software Foundation. Дата обращения: 27 августа 2026. Архивировано 18 июля 2018 года.
  40. Essential classes: Regular Expressions: Quantifiers: Differences Among Greedy, Reluctant, and Possessive Quantifiers. The Java Tutorials. Oracle Corporation. Дата обращения: 27 августа 2026. Архивировано 7 октября 2020 года.
  41. Bormann, Carsten & Bray, Tim, I-Regexp: An Interoperable Regular Expression Format, Internet Engineering Task Force, RFC 9485, doi:10.17487/RFC9485, <https://datatracker.ietf.org/doc/html/rfc9485>. Проверено 11 марта 2024. 
  42. Perl Regular Expression Matching is NP-Hard. perl.plover.com. Дата обращения: 21 ноября 2019. Архивировано 7 октября 2020 года.
  43. Named capturing group. MDN Web Docs. Дата обращения: 27 августа 2026.
  44. Named backreference. MDN Web Docs. Дата обращения: 27 августа 2026.
  45. Wall, Larry Perl 5: perlre.pod. GitHub (18 октября 1994). Дата обращения: 27 августа 2026. Архивировано 4 декабря 2024 года.
  46. Navarro, Gonzalo (10 ноября 2001). “NR-grep: a fast and flexible pattern-matching tool” (PDF). Software: Practice and Experience. 31 (13): 1265—1312. DOI:10.1002/spe.411. S2CID 3175806. Архивировано из оригинала (PDF) 2020-10-07. Дата обращения 2026-08-27. Используется устаревший параметр |url-status= (справка)
  47. Hybrid NFA/DFA engine. regex-automata documentation. docs.rs. Дата обращения: 27 августа 2026.
  48. 1 2 RE2 - Regular Expressions for Safety and Speed. regular-expressions.info. Дата обращения: 27 августа 2026.
  49. PCRE2 Release Notes. PCRE2 Project. Дата обращения: 27 августа 2026.
  50. ICU Downloads. International Components for Unicode. Unicode Consortium. Дата обращения: 27 августа 2026.
  51. Regular Expressions in .NET. regular-expressions.info. Дата обращения: 27 августа 2026.
  52. Horowitz, Bradley A fall sweep. Google Blog (24 октября 2011). Дата обращения: 27 августа 2026. Архивировано 21 октября 2018 года.
  53. Structured Output: Constrained Decoding and Grammars. Grasp Study Paths. Grasp Study (1 июля 2024). Дата обращения: 27 августа 2026.

Литература

  • Aho, Alfred V. Algorithms for finding patterns in strings // Handbook of Theoretical Computer Science, volume A: Algorithms and Complexity. — The MIT Press, 1990. — P. 255–300.
  • Aho, Alfred V. Chapter 10. Patterns, Automata, and Regular Expressions // Foundations of Computer Science / Alfred V. Aho, Jeffrey D. Ullman. — 1992.
  • Aycock, John (Июнь 2003). “A brief history of just-in-time”. ACM Computing Surveys. 35 (2): 97—113. DOI:10.1145/857076.857077.
  • Friedl, Jeffrey E. F. Mastering Regular Expressions. — O'Reilly Media, 2002. — ISBN 978-0-596-00289-3.
  • Goyvaerts, Jan. Regular Expressions Cookbook / Jan Goyvaerts, Steven Levithan. — O'Reilly, 2009. — ISBN 978-0-596-52068-7.
  • Stubblebine, Tony. Regular Expression Pocket Reference. — O'Reilly, 2003. — ISBN 978-0-596-00415-6.