Построение эффективных регулярных выражений. Оператор 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