Построение эффективных регулярных выражений. Оператор qr/…/ и объекты регулярных выражений.
10.2 Оператор qr/…/ и проблемы при использовании модификатора o
Когда в операторе qr/…/ используется модификатор o и есть интерполируемые переменные, этот объект регулярного выражения больше не модифицируется, если ему даже присваивается значение. Т.е. он как бы привязан к действующим на момент первого выполнения значениям интерполируемых переменных. Поэтому не используйте модификатор o с объектами регулярных выражений, если не хотите труднонаходимых сюрпризов. Такой пример:
my $a=$_='ab';
my $re=qr"$a"o;
for my $i (0..1)
{ print "$re\n";
print "Found $&\n" if /$re/;
$_=$a='cd';
$re=qr"$a";
}За циклом мы создаем объект регулярного выражения $re с интерполяцией переменной $a. В цикле перед вторым проходом переменная $a меняет значение, и после этого опять повторяется оператор $re=qr"$a". На печать выходят оба найденных значения:
(?-xism:ab) Found ab (?-xism:cd) Found cd
Теперь внесем первый оператор my $re=qr"$a"o в цикл:
my $a=$_='ab';
for my $i (0..1)
{ my $re=qr"$a"o;
print "$re\n";
print "Found $&\n" if /$re/;
$_=$a='cd';
$re=qr"$a";
}Напечатается
(?-xism:ab) Found ab (?-xism:ab)
Мы видим следующее: хотя переменная $a поменяла свое значение на cd, объект регулярного выражения $re стал как бы константой и продолжает хранить старое ее значение $a='ab', несмотря на то, что мы присваиваем $re новое значение. Виной этому модификатор o. Без него пример работает так, как ожидается:
my $a=$_='ab';
for my $i (0..1)
{ my $re=qr"$a";
print "$re\n";
print "Found $&\n" if /$re/;
$_=$a='cd';
$re=qr"$a";
}И печатает, как и в первом случае,
(?-xism:ab) Found ab (?-xism:cd) Found cd
Если интерполируемых переменных нет, то опять все работает так, как ожидается:
my $a=$_='ab';
my $re=qr"ab"o;
for my $i (0..1)
{ print "$re\n";
print "Found $&\n" if /$re/;
$_=$a='cd';
$re=qr"cd";
}Выводит
(?-xism:ab) Found ab (?-xism:cd) Found cd