Интерполяция переменных и метасимволы \U, \u, \L, \l, \Q, \E
Если интерпретатор видит, что регулярное выражение требует интерполяции чего-нибудь, то это выражение будет транслироваться всякий раз перед его выполнением. Если вы уверены, что интерполируемые переменные не меняют своего значения, то можете поставить ко всему регулярному выражению модификатор o, который отменит повторную компиляцию такого шаблона. Вместо этого будет использоваться его внутреннее скомпилированное представление, которое получилось перед первым его выполнением. А во внутреннем представлении переменные заменены их значениями.
Поэтому, если эти переменные изменят свое значение, то это не повлияет на такое регулярное выражение, в нем все равно будут применяться те значения интерполированных переменных, которые были во время компиляции шаблона.
Сравните:
my $a='abc'; $_='abc'; for my $count (0..1) { print "$&\n" if /^$a$/; $a='123'; $_='123'; }
Напечатается
abc 123
и
my $a='abc'; $_='abc'; for my $count (0..1) { print "$&\n" if /^$a$/o; $a='123'; $_='123'; }
Напечатается только
abc
Во втором случае в обоих повторах цикла совпадение отыскивается по тому же самому регулярному выражению /^abc$/, хотя переменная $a поменяла значение на '123'. В результате при втором повторе цикла совпадение с шаблоном не обнаруживается.
Модификатор o, как и модификаторы g и с, могут быть применены только ко всему регулярному выражению и не могут встречаться внутри него.
Как будут интерполироваться переменные, которые устанавливаются внутри регулярного выражения, в частности, нумерованные переменные $1, $2, …, $99? Так же, как и ваши переменные: своим значением, которое они имели до работы этого регулярного выражения. Поэтому не надейтесь, что в ходе выполнения регулярного выражения вы будете получать самые "свежие" их значения. Другое дело - встроенный код Perl и динамические регулярные выражения (которые мы рассмотрим в дальнейшем): здесь нет интерполяции переменных, а используются их текущие значения.
Внутри классов тоже происходит интерполяция переменных. В данном примере мы интерполируем два значения переменных с двумя индексами:
my @a=([1,2],[3,4]); $_='23'; print $& if /^[$a[0][1]$a[1][0]]{2}$/;
После интерполяции регулярное выражение будет иметь вид /^[23]{2}$/.
Разумеется, в классы интерполируются также и переменные, содержащие метасимволы классов:
$_='123abc'; my $a='^\d'; print $& if /[$a]+/;
Будет напечатано abc.
После интерполяции регулярное выражение будет иметь вид /[^\d]+/.
При попытке интерполировать неопределенное значение появится предупреждение об использовании неинициализированного значения:
#!/usr/bin/perl -w use strict; $_='z'; my $a=undef; /^$a$/;
Будет напечатано:
Use of uninitialized value in concatenation (.) or string at a.pl line 6.
Если мы хотим интерполировать внутрь строки значение переменной $n, то просто напишем "\$n=$n text". А если надо интерполировать не число $n, а число $n+1 или другое выражение, тогда как? Можно, конечно, написать так: "\$n+1=".($n+1)." text", но это не будет интерполяция внутрь строки. Здесь можно прибегнуть к рассмотренному приему интерполяции кода внутрь строки: "\$n+1=${\($n+1)} text". Аналогично можно интерполировать выражения внутрь регулярных выражений. К примеру, если мы вместо квантификатора хотим использовать значение переменной $n, то напишем
$_='a'; my $n=1; /^(a{$n})$/; print $1;
Напечатается a.
Если хотим, к примеру, использовать квантификатор со значением $n+1, то можно написать так:
$_='aa'; my $n=1; /^(a{${\($n+1)}})$/; print $1;
Напечатается aa.