Опубликован: 18.06.2007 | Доступ: свободный | Студентов: 1354 / 35 | Оценка: 4.14 / 3.29 | Длительность: 12:44:00
ISBN: 978-5-94774-604-4
Лекция 12:

Динамические регулярные выражения

< Лекция 11 || Лекция 12: 12345 || Лекция 13 >
Аннотация: Рассматривается применение динамических регулярных выражений при сложном поиске и поиске вложенных конструкций.

Динамическое регулярное выражение вводится конструкцией

(??{ код Perl })

В процессе его работы выполняется этот код Perl. Результат выполнения (строка или объект регулярного выражения ) подставляется на место этой конструкции. Как я уже замечал, в коде Perl переменные не интерполируются, а каждый раз используются их самые "свежие" значения.

Это очень мощная конструкция, которая позволяет конструировать подшаблоны "на лету" в зависимости от результатов работы предыдущих подшаблонов. Подобные конструкции в Perl возможны потому, что регулярные выражения в нем встроены в сам язык, а не применяются в виде набора подпрограмм, как, например, в PHP. Если условный шаблон (? if then [ | else ]) позволял выбирать один из двух подшаблонов в зависимости от предыдущего счета, то динамическое регулярное выражение позволяет конструировать практически любой шаблон, который может понадобиться. Конечно, обработка динамического регулярного выражения замедлит выполнение программы, и его не следует применять, если можно обойтись более простыми и быстрыми конструкциями.

Динамическое регулярное выражение должно подставлять целый подшаблон, а не какую-либо его незаконченную часть. Вот пример:

$_='abc';
print 'OK' if /ab(??{'c'})/;

Динамическое регулярное выражение подставляет символ c, в результате обнаруживается совпадение с текстом abc. Теперь попробуем подставить квантификатор *:

$_='abc';
print 'OK' if /ab(??{'*'})/;

Получаем сообщение

Quantifier follows nothing in regex; …

Perl после выполнения кода внутри динамического регулярного выражения пытается скомпилировать возвращаемое значение во внутреннее представление для регулярного выражения, но находит ошибку синтаксиса, т.к. квантификатор не может начинать шаблон.

При использовании динамических регулярных выражений, как и при использовании встроенного кода Perl, может возникнуть сообщение:

panic: top_env

Это значит, что интерпретатор не может определить ошибку, которая происходит во время выполнения кода Perl, и вы должны ее найти и исправить.

Авторы книг и пособий упускают такой момент: при компиляции возвращаемого значения динамического регулярного выражения не учитываются модификаторы, которые стоят вне этого возвращаемого динамическим регулярным выражением подшаблона.

Поэтому внутри динамического регулярного выражения необходимо поставить все нужные ему модификаторы. За пределами динамического регулярного выражения восстанавливается действие модификаторов как перед входом в это динамическое регулярное выражение. Т.е. динамические регулярные выражения действуют автономно от остальной части всего шаблона. Операторы изменения регистра символов \L, \U, … и оператор \Q, использованные внутри динамического регулярного выражения, также перестают действовать за пределами этого выражения.

12.1. Примеры применения динамических регулярных выражений

Для начала приведу простой и немного искусственный пример: пусть нам надо проверить правильность строки

Далее стоит 13 нулей: 0000000000000
	
Причем, число нулей может быть произвольным от 1 и более, например,

Далее стоит 2 нуля: 00

Нам надо составить регулярное выражение, которое проверяет, что число соответствует количеству нарисованных нуликов. Этот шаблон может выглядеть так:

(\d+) \D+(??{"0{$1}"})$

Работает он таким образом: вначале в переменную $1 захватывается число (13, 2 и т.д.).

Затем идет пропуск всех нецифровых символов. Внутри динамического регулярного выражения конструируется подшаблон, состоящий из символа нуля и числителя, который равен содержимому переменной $1. Для фразы

Далее стоит 13 нулей: 0000000000000

Весь шаблон после подстановки результата выполнения кода Perl будет иметь вид

(\d+) \D+0{13}$

В случае строки

Далее стоит 2 нуля: 00

Это регулярное выражение примет вид

(\d+) \D+0{2}$

Даже для строки

Далее стоит 0 нулей:

будет найдено совпадение.

< Лекция 11 || Лекция 12: 12345 || Лекция 13 >
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия