Опубликован: 18.06.2007 | Уровень: специалист | Доступ: свободно
Лекция 9:

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

И еще аналогичный и очень интересный пример:

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

Будет напечатано

$_=z $a=z
$&=z
$_=2 $a=z

Из результата мы видим следующее:

  • поиск завершился успешно;
  • переменная $& должна бы содержать 2, а содержит z ;
  • во встроенном коде мы присвоили переменной $_ z, и $a тут же получила это же значение;
  • вне оператора поиска переменная $_ сохраняет свое старое значение 2, а $a хранит полученное во встроенном коде значение z.

Можно сделать вывод, что внутри регулярного выражения переменная $_ является синонимом переменной, содержащей целевой текст, как и в операторах map и for (), и переменная $_ локализуется внутри регулярного выражения. Поэтому изменять $_ внутри регулярного выражения так же опасно, как и переменную с целевым текстом.

И еще относительно встроенного кода: встроенный код, который содержится внутри интерполируемых переменных, тоже выполняется, но для этого нужна директива

use re 'eval';

При выполнении скрипта

$_='aaa';
my $a='(?{print "OK "})';
print "$&" if /^aaa$a$/;

Возникнет ошибка

Eval-group not allowed at runtime, use re 'eval' in regex m/^aaa(?{print "OK"})$/ at a.pl line 7.

С директивой use re 'eval' все в порядке:

use re 'eval';

$_='aaa';
my $a='(?{print "OK "})';
print "$&" if /^aaa$a$/;

Вывод: OK aaa.

Заметим, что эта директива не действует внутри встроенного кода:

my $a='(?{use re "eval"; print "OK "})';
print "$&" if /^aaa$a$/;

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

Гулзира Урбисинова
Гулзира Урбисинова
как получить сертификаты все тесты пройдены
Сергей Крупко
Сергей Крупко
Как оплатить курс?
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия