Текст и повседневные инструменты · Текстовый инструментарий
От Клини до JavaScript: краткая история регулярных выражений
· Фон
регулярные выражения javascript история вычислений
Отслеживает регулярные выражения из теории автоматов 1950-х годов через ed, grep и Perl до версии JavaScript в каждом браузере, объясняя, почему синтаксис выглядит именно так и какие функции когда появились.
Странный маленький язык, который все знают наполовину: почему синтаксис регулярных выражений кажется древним и непоследовательным
Регулярные выражения напоминают язык, собранный в разные эпохи, потому что, по сути, они таковыми и являются. Компактное ядро чередования, повторения и группировки превратилось из математической записи в команды редактора, фильтры командной строки и функции языка программирования. Пунктуация сохранилась, хотя каждый хост добавил свои удобства, ограничения и терминологию.
Эта история объясняет, почему шаблон может выглядеть знакомым, но вести себя по-разному в grep, Perl, Python и JavaScript. «Регулярное выражение» — это фамилия, а не одна универсальная грамматика. Для аналитика-самоучки полезный урок — не запоминать каждый диалект, а определить движок, флаги и правила замены, прежде чем доверять заимствованному шаблону.
Регулярные события Клини — математика конечных автоматов 1950-х годов, которая дала нам звезду
Работа Стивена Коула Клини о конечных автоматах и «регулярных событиях» заложила теоретический фундамент в 1950-х годах. Его обозначения описывали наборы последовательностей символов с использованием таких операций, как объединение, конкатенация и замыкание. Операция замыкания стала звездой Клини: `A*` означает ноль или более повторений, взятых из A, а не просто «повторить один или несколько раз».
Формальные регулярные языки, распознаваемые конечными автоматами, уже, чем многие конструкции, которые сейчас продаются под маркой регулярных выражений. Например, обратные ссылки могут выражать условия, выходящие за рамки этой классической модели. Таким образом, современные движки сохраняют историческое название и большую часть обозначений, реализуя языки шаблонов, возможности и стратегии выполнения которых выходят за рамки исходного математического объекта Клини.
Томпсон, Эд и grep — как регулярное выражение вошло в редактирование текста в инструментах Unix конца 1960-х и начала 1970-х годов.
Кен Томпсон связал эту теорию с работающими текстовыми инструментами. В его 1968 сообщениях к статье ACM описывалась компиляция регулярных выражений в машинный код для поиска текста, а его ранняя работа редактора помогла поместить сопоставление с образцом в родословную Unix. Редактор `ed` использовал регулярные выражения в командах, которые выделяли и преобразовывали совпадающие строки.
Имя `grep` произошло от команды `ed`, обычно отображаемой как `g/re/p`: глобально выберите строки, соответствующие регулярному выражению, и распечатайте их. Ранний grep не представлял собой сегодняшний набор опций GNU, а более поздние базовая и расширенная формы POSIX различались. Устойчивое изменение имело практический смысл: небольшой символьный язык стал повседневным интерфейсом для поиска текста.
Perl и PCRE — расширения, которые добавили нежадные квантификаторы, обходной путь и синтаксис, который сегодня копирует большинство инструментов.
Perl сделал более богатый язык шаблонов центральным элементом программирования общего назначения. Во всех его версиях программисты встречали группы захвата, обратные ссылки, утверждения, ленивые квантификаторы и модификаторы шаблонов в одной хорошо заметной экосистеме. В документации Perl 5 записаны такие конструкции, как `*?` для минимального соответствия и `(?=...)` для положительного просмотра вперед, а также многие функции, отсутствующие в старых формах Unix.
Вернее сказать, что Perl популяризировал этот стиль, чем приписывать ему изобретение всех расширений. PCRE намеренно предлагал Perl-совместимый синтаксис, в то время как другие движки приняли отдельные идеи и отвергли другие. Общая пунктуация может скрывать различную семантику, поведение или производительность Unicode. Термин «Perl-подобный», следовательно, описывает широкое влияние, а не гарантию того, что шаблон Perl является переносимым.
Perl популяризировал более широкий практический язык шаблонов; более поздние двигатели заимствованы выборочно
JavaScript стандартизировал свои собственные объекты `RegExp` и литеральный синтаксис, например `/pattern/gi`, для программ, работающих в браузерах и других средах ECMAScript. Его особенности включают захватывающие и нефиксирующие группы, обратные ссылки, просмотр вперед, ленивые квантификаторы и классы символов. В более поздних выпусках в спецификацию ES2018 были добавлены именованные группы захвата и утверждения просмотра назад.
JavaScript — это не PCRE или Python с другими разделителями. Доступность функций зависит от версии ECMAScript, реализованной в движке, а флаги являются частью поведения, а не украшением. Руководство по регулярным выражениям MDN является актуальным практическим справочником по синтаксису браузера, но даже валидные примеры JavaScript могут опираться на флаги, которые конкретный интерфейс не предоставляет.
JavaScript получил именованные группы и функцию просмотра назад в ES2018, но механизмы и флаги по-прежнему различаются.
Браузеры помещают механизм регулярных выражений JavaScript рядом с обычной работой с текстом. Страница может скомпилировать шаблон, подсчитать совпадения и передать его `String.prototype.replace` без отправки текста в специализированный сервис регулярных выражений. Эта доступность делает возможным интерфейс поиска и замены на стороне браузера, хотя окружающую страницу по-прежнему необходимо проверять отдельно на предмет более широких требований конфиденциальности.
Реализация ToolAcre вызывает `new RegExp` внутри `compilePattern`, перехватывает ошибки компиляции и вместо выдачи возвращает ошибку. `findReplace` подсчитывает совпадения перед применением стандартной операции замены. В результате токены замены JavaScript, такие как ссылки на захват, следуют за строкой хоста API; Синтаксис регулярных выражений и синтаксис замены — родственные, но разные языки.
Чего это не касается — теорию формального языка за пределами основ и внутренние характеристики движка.
Эта короткая история не доказывает эквивалентность практических механизмов и конечных автоматов, не рассматривает алгоритмы выполнения регулярных выражений и не ранжирует реализации по скорости. Отслеживание с возвратом, методы линейного времени и патологические паттерны заслуживают отдельного рассмотрения. Защита ToolAcre перехватывает синтаксические ошибки, но не обнаруживает допустимое выражение, которое выполняет чрезмерный возврат и останавливает основной поток браузера.
Кроме того, временная шкала не относит каждый метасимвол к одному изобретателю. Функции программного обеспечения часто появлялись через статьи, редакторы, языковые версии и совместимые повторные реализации, а не через одну чистую передачу. Источники подтверждают конкретные вехи; они не оправдывают более простую историю о том, что один продукт создал массовое современное регулярное выражение или что более поздние версии унаследовали идентичное поведение.
Вывод: режим регулярных выражений Text Toolkit — это разновидность JavaScript, поэтому шаблоны из документации браузера работают так, как написано.
Практическое наследование видно в ToolAcre: включите Regex, и текст поиска компилируется движком браузера JavaScript. Если оставить Regex выключенным, метасимволы будут экранированы, что сделает поиск буквальным. Все слово обрамляет выражение границами `` в стиле ASCII, а чувствительность к регистру определяет, сопровождает ли флаг `i` всегда присутствующий глобальный флаг `g`.
Эта последняя деталь корректирует общее обещание схемы о том, что шаблоны документации браузера работают так, как написано. ToolAcre не предоставляет флаги multiline, dot-all, Sticky или Unicode, поэтому примеры, требующие `m`, `s`, `y`, `u` или `v`, требуют адаптации, и некоторые из них невозможно воспроизвести там. Используйте этот инструмент для проверки поддерживаемых шаблонов JavaScript, считывания количества замен и отмены действий перед уточнением.