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

Интерполяция переменных и метасимволы \U, \u, \L, \l, \Q, \E

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >

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

Т.к. регулярное выражение предварительно обрабатывается как строка, заключенная в кавычки (если оно не было ограничено апострофами), то интерполяция значений переменных и результата выполнения кода 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

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

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия