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