Глава 15
Регулярные выражения
Текст редко приходится сравнивать с точной строкой целиком: чаще нужно узнать, есть ли в нём число, какие фрагменты похожи на образец и чем разделены части. Такой образец задаёт регулярное выражение — строковый шаблон, описывающий форму текста, а не его буквальное содержимое. Встроенные функции REGEXISMATCH, REGEXMATCH, REGEXEXTRACT, REGEXMATCHES, REGEXEXTRACTALL, REGEXSPLIT, REGEXREPLACE и REGEXCOUNT проверяют, извлекают, разделяют, заменяют и считают совпадения.
Аргументы и режимы
Параметры STRING text и pattern задают текст и шаблон. Необязательный STRING modes объединяет режимы, например "im"; без него поиск выполняется в обычном режиме.
| Режим | Назначение |
|---|---|
i | Не различать строчные и прописные буквы. |
m | Считать начало и конец каждой строки отдельными границами для ^ и $. |
s | Разрешить точке . совпадать с переводом строки. |
x | Игнорировать незначащие пробелы в образце, если они не экранированы и не входят в набор символов. |
Шаблон обрабатывается движком .NET Regex. В таблицах приведены основные конструкции, применяемые в подтверждённых примерах Axiom; они составляют язык шаблона внутри строкового аргумента, а не синтаксис самой программы.
Основные правила
Нулевая группа представляет всё совпадение, а захватывающие группы нумеруются по правилам .NET, включая явно заданные непоследовательные номера. От этой нумерации зависит, что вернёт функция, выбирающая группу по номеру.
Пустой результат тоже имеет свой договор. REGEXMATCHES и REGEXEXTRACTALL при отсутствии совпадений возвращают массив 1 TO 0. REGEXSPLIT также возвращает массив строк, но при отсутствии разделителя сохраняет непустой текст одним элементом.
Ошибкой считаются три случая: неверный pattern, неизвестный modes и отрицательный groupNumber — каждый из них вызывает MB3007. Отсутствующая положительная группа ошибкой не является и даёт пустую строку. При count = 0 REGEXREPLACE пропускает проверку pattern и modes, однако выражения аргументов всё равно вычисляются.
Синтаксис шаблонов
Шаблон записывается внутри строкового аргумента, поэтому к нему применяются правила строк Axiom. Обратная косая черта в строке сохраняется буквально, и для класса цифр pattern содержит одну косую черту: \d. Две косые черты нужны самому шаблону для поиска буквальной косой черты. Пример: pattern_backslash.axm.
Буквальные символы и классы
| Запись | Значение |
|---|---|
abc | Буквальное совпадение со строкой abc. |
. | Одна единица UTF-16, кроме LF (CHR(10)). CR (CHR(13)) совпадает и без режима s. В режиме s точка включает также LF. |
[abc] | Один символ из набора: a, b или c. |
[^abc] | Один символ, кроме перечисленных в наборе. |
[a-z] | Один символ из диапазона. |
\d | Цифра. |
\D | Любой символ, кроме цифры. |
\w | Буква, десятичная цифра Unicode, комбинируемый знак категории Mn или соединительный знак пунктуации, включая подчёркивание. Например, знак U+0301 также совпадает с \w. |
\W | Любой символ, кроме \w. |
\s | Пробельный символ: пробел, табуляция, перевод строки и подобные. |
\S | Любой символ, кроме пробельного. |
\t, \r, \n | Табуляция, возврат каретки и перевод строки. |
\\ | Обратная косая черта как буквальный символ. |
\., \*, \+, \? | Спецсимвол как обычный текст, а не как команда regex. |
Повторы и жадность
Повторители относятся к непосредственно предшествующему элементу: символу, классу или группе. Скобки позволяют объединить последовательность перед применением повторителя.
| Запись | Значение |
|---|---|
* | Ноль или больше повторений предыдущего элемента. |
+ | Одно или больше повторений предыдущего элемента. |
? | Ноль или одно повторение предыдущего элемента. |
{n} | Ровно n повторений. |
{n,} | Не меньше n повторений. |
{n,m} | От n до m повторений включительно. |
*?, +?, ??, {n,m}? | Нежадные формы: берут минимально возможное совпадение. |
Шаблон "[,;]\s*" выбирает запятую либо точку с запятой и следующие за ней пробельные символы; повторитель * разрешает отсутствие таких пробелов.
Границы, группы и ветвление
| Запись | Значение |
|---|---|
^ | Начало текста. В режиме m также начало каждой строки. |
$ | Конец текста либо позиция перед завершающим LF. В режиме m также позиция перед каждым LF. CR перед LF не пропускается автоматически. |
\A, \z | Строгое начало и конец всего текста независимо от режима m. Для проверки всего текста используйте "\Aa\d+\z". |
(...) | Захватывающая группа. Её можно извлекать через REGEXEXTRACT и REGEXEXTRACTALL. |
(?:...) | Незахватывающая группа: группирует шаблон, но не создаёт номер группы. |
a|b | Альтернатива: подходит либо a, либо b. |
\1, \2 | Обратная ссылка на уже захваченную группу по номеру. |
(?<name>...) | Именованная группа .NET. |
\k<name> | Обратная ссылка на именованную группу. |
Проверки без захвата
| Запись | Значение |
|---|---|
(?=...) | Положительный просмотр вперёд: справа должен стоять указанный шаблон. |
(?!...) | Отрицательный просмотр вперёд: справа не должно быть указанного шаблона. |
(?<=...) | Положительный просмотр назад: слева должен стоять указанный шаблон. |
(?<!...) | Отрицательный просмотр назад: слева не должно быть указанного шаблона. |
Unicode и пустые совпадения
Движок сопоставляет единицы UTF-16. Для текста "😀" шаблон "." имеет два совпадения, пустой шаблон — три, по одному на каждой границе. Извлечённый фрагмент может содержать половину суррогатной пары.
Пустой STRING от REGEXMATCH может означать отсутствие совпадения либо успешное пустое совпадение. REGEXISMATCH позволяет их различить. Для пустого text и пустого pattern функция REGEXMATCHES возвращает один пустой элемент; REGEXSPLIT при пустом text возвращает пустой массив. При непустом text разбиение сохраняет крайние пустые части и захватывающие группы разделителя.
Предел времени поиска
Для отдельного поиска установлен предел пять секунд. Превышение вызывает MB3007, доступную для обработки в TRY/CATCH. Предел относится к поиску движка, а не к суммарному времени программы или всех совпадений.
Отмена и ресурсы
При остановке программы исполнитель проверяет запрос отмены перед поиском, после него и между совпадениями. Отмена завершает запуск и не является ошибкой MB3007: пользовательские CATCH и FINALLY не выполняются. Уже начавшийся отдельный поиск движка не прерывается немедленно; до следующей проверки отмены он может занять до пяти секунд. Общее время всех совпадений не ограничивается пятью секундами.
Стоимость самих функций различна. Исполнитель хранит не более 128 последних использованных сочетаний шаблона и режимов. Вытеснение записи влияет только на повторную подготовку шаблона, а не на результат. Разные записи одинаковых режимов, например i, I и ii, не создают отдельные сохранённые строки режимов.
REGEXCOUNT подсчитывает совпадения без коллекции их объектов. Массивные функции выделяют память под результат; число результатов и их длина по-прежнему влияют на расход памяти. REGEXREPLACE выполняет буквальную замену за один проход без предварительного повторного поиска.
Сообщения об ошибках
В поле Message значения ошибки сохраняются английское описание причины и имя аргумента. Неверный шаблон сообщает Invalid pattern, смещение и вид ошибки разбора; неизвестный режим — Unknown mode и допустимые буквы; отрицательная группа или количество — cannot be negative; превышение времени — Pattern matching exceeded the 5 second timeout. Смещение разбора относится к строке шаблона. Поля Line и Column указывают место вызова в программе.
Темы главы
Формы вызова и правила каждой функции собраны на отдельных страницах.
Когда регулярное выражение лучше обычного поиска
Шаблоны подходят для проверки формата, извлечения групп и работы с переменным разделителем. Для буквального фрагмента используйте строковый поиск и замену.