Регулярные выражения Perl и их применение


         

Интерполяция переменных и кода в регулярне выражение


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

Авторы книг по Perl не упоминают, как происходит интерполяция переменной с индексами, ведь символ [ является метасимволом внутри шаблонов.

my @a=('abc','def'); $_='def'; print $& if /^$a[1]$/;

Напечатается def.

Как видим, конструкция […] после имени переменной интерпретируется как индекс. Если же интерполируется скалярная переменная, после которой идет класс, то транслятор выдает ошибку:

#!/usr/bin/perl -w use strict;

my $a=2; $_='21'; print $& if /^$a[1]$/;

Global symbol "@a" requires explicit package name at a.pl line 6. Execution of a.pl aborted due to compilation errors.

Здесь не поможет заключение имени переменной в фигуный скобки: ${a}, ошибка останется той же. Если отделить имя переменной от квадратной скобки пробелом, то программа работает верно:

#!/usr/bin/perl -w use strict;

my $a=2; $_='21'; print $& if /^$a [1]$/x;

На выходе имеем 21.

А если мы не планируем использовать модификатор x? Тогда может помочь такое искусственное решение:

my $a=2; $_='21'; print $& if /^$a(?#)[1]$/;

Опять получаем 21.

Мы отделили имя переменной от скобки конструкцией комментария. Т.к. интерполяция переменных происходит раньше удаления комментариев, этот метод работает. Также можно было бы разделить имя со скобкой каким-либо нейтральным подшаблоном, например:

my $a=2; $_='21'; print $& if /^$a(?=)[1]$/;

И снова выводится 21.

Опережающая проверка (?=) всегда возвращает истину, т.к. пустой фрагмент в тексте можно встретить всюду.

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

my $a=2; $_='21'; print $& if /^${a}a{0}[1]$/;

Опять 21.

Мы разделили имя и класс подшаблоном a{0}, который равносилен пустому фрагменту.

Теперь рассмотрим интерполяцию переменной с двумя индексами:

my @a=([1,2],[3,4]); $_='2'; print $& if /^$a[0][1]$/;

На печати получаем 2. Отсюда вывод: конструкции […] интепретируются как индексы переменной, если они идут непосредственно после ее имени. Отделение классов от индексов происходит аналогично уже рассмотренным случаям с одним индексом.

Массивы в регулярные выражения тоже интерполируются как в строку, ограниченную двойными кавычками:

$"=','; my @a=(1,2,3); $_='1,2,3'; print $& if /^@a$/;

На печать выйдет

1,2,3,4

После интерполяции массива @a с учетом разделителя $"=',' регулярное выражение стало эквивалентно такому: /^1,2,3,4$/.




Содержание  Назад  Вперед