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

Встроенный код, переменные local и my

Аннотация: Рассматривается применение встроенного кода, ключевое слово local и переменные my, а также статическая и динамическая область видимости и связывание переменных.

Встроенный код Perl вставляется в регулярное выражение конструкцией

(?{ код Perl })

При этом открывающую фигурную скобку нельзя отделять от знака вопроса, а закрывающую фигурную скобку - от закрывающей круглой скобки.

Иногда при использовании встроенного кода Perl может запаниковать и при выполнении программы выдать такое сообщение:

panic: top_env

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

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

(?  if  then )

или

(?  if  then  |  else  )

стоит встроенный код, то результат его выполнения не запоминается в переменной $^R.

Этой переменной также можно присваивать значения напрямую. В работе с переменной $^R используется концепция динамической видимости переменных: если при возврате в процессе перебора с возвратами в шаблоне осуществляется проход (справа налево) конструкции встроенного кода, то переменная $^R восстанавливает свое предыдущее значение, которое она имела перед последним выполнением этого кода при движении слева направо по шаблону. Таким образом, эта специальная переменная всегда хранит свое самое "свежее" значение. Рассмотрим такие примеры.

my $a='1';
$_='2';
$^R='a';
print "Found\n" if /^(?{print 'OK '; $a='z'})(?:23)*$/;
print $^R;

Будет напечатано OK a. Это означает, что оператор поиска работал, но поиск завершился неудачей. И еще: что при неудачном поиске переменная $^R не меняет своего значения.

my $a='1';
$_='2';
$^R='a';
print "Found\n" if /^(?{print 'OK '; $a='z'})2$/;
print $^R;

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

OK Found
z

При успешном поиске переменная $^R изменила свое значение на то, что было косвенно присвоено ей во встроенном коде.

my $a='1';
$_='2';
$^R='a';
print "Found\n" if /^(?(?{print 'OK '; $a='z'})2)$/;
print $^R;

На печать пойдет

OK Found
a

В этом примере встроенный код стоял в условии условной конструкции (? if then ), поэтому переменная $^R не изменила своего значения, хотя поиск был успешным.

И рассмотрим еще такие примеры.

my $a='1';
print "$&" if $a =~ /^1$/;

Напечатается 1. Пока ничего особенного не видно. Теперь добавим в пример встроенный код, который присваивает значение переменной $a:

my $a='1';
print "$&" if $a =~ /^1(?{$a='z'})$/;

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

my $a='1';
$b='2';
print "$&" if $a =~ /^1(?{$b='z'})$/;

Здесь печатается, как и положено, 1.

Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия