Привет.
Лексических переменных my нет в таблице имен. Наверно, поэтому без /ee не работает.
===
Perl Cookbook
1.8. Расширение переменных во входных данных
*** Проблема ***
Имеется строка, внутри которой присутствует ссылка на переменную:
You owe $debt to me.
Требуется заменить имя переменной $debt в строке её текущим значением.
*** Решение ***
Если все переменные являются глобальными, воспользуйтесь подстановкой
с символическими ссылками:
$text =~s/\\$(\\w+)/${$1}/g;
Hо если среди переменных могут встречаться лексические (mу)
переменные, следует использовать /её:
$text =~ s/(\\$\\w+)/$1/gee;
*** Комментарий ***
Первый способ фактически сводится к следующему: мы ищем нечто похожее
на имя переменной, а затем интерполируем её значение посредством
символического разыменования (dereferencing). Если $"( содержит строку
somevar, то ${$1} будет равно содержимому $somevar. Такой вариант не
будет работать при действующей директиве use st rict \' rets , потому
что она запрещает символическое разыменование. Приведём пример:
use vars qw($rows $cols);
no strict \'rets\'; # для приведённого ниже ${$1} my $text;
($rows, $cols) = (,^, 80):
$text = q(i am $ rows high and $cols long); # апострофы! $text =~
s/\\$(\\w+)/${$1}/g;
print $text;
I am 24 high and 80 long
Возможно, вам уже приходилось видеть, как модификатор подстановки /е
используется для вычисления заменяющего выражения, а не строки.
Допустим, вам потребовалось удвоить каждое целое число в строке:
$text = "i am 17 years old";
$text ="" s/(\\d+)/2 * $1/eg;
Перед запуском программы, встречая /е при подстановке, Perl
компилирует код заменяющего выражения вместе с остальной программой,
задолго до фактической подстановки. При выполнении подстановки $1
заменяется найденной строкой. В нашем примере будет вычислено
следующее выражение:
2 * 17
Hо если попытаться выполнить следующий фрагмент:
$text = \'i am $age years old\'; # Обратите внимание на апострофы!
$text =~ s/(\\$\\w+)/$1/eg; # HЕВЕРHО
при условии, что $text содержит имя переменной $AGE, Perl послушно
заменит $1 на $AGE и вычислит следующее выражение:
\'$AGE\'
В результате мы возвращаемся к исходной строке. Чтобы получить
значение переменной, необходимо снова вычислить результат. Для этого в
строку добавляется ещё один модификатор /e:
$text =~ s/(\\$\\w+)/$1/eeg; # Hаходит переменные mу()
Да, количество модификаторов /е может быть любым. Только первый
модификатор компилируется вместе с программой и проверяется на
правильность синтаксиса. В результате он работает аналогично
конструкции eval {BLOCK}, хотя и не перехватывает исключений.
Возможно, лучше провести аналогию с do {BLOCK}.
Остальные модификатора! /е ведут себя иначе и больше напоминают
конструкцию eval "STRING". Они не компилируются до выполнения
программы. Маленькое преимущество этой схемы заключается в том, что
вам не придётся вставлять в блок директиву no strict \'refs\'. Есть и
другое огромное преимущество: этот механизм позволяет находить
лексические переменные, созданные с помощью my, - символическое
разыменование на это не способно.
В следующем примере модификатор /х разрешает пропуски и комментарии в
шаблоне подстановки, а модификатор /е вычисляет правостороннее
выражение на программном уровне. Модификатор /е позволяет лучше
управлять обработкой ошибок или других экстренных ситуаций:
# Расширить переменные в $text. Если переменная не определена,
# вставить сообщение об ошибке.
$text =~ s{
\\$ # Hайти знак доллара
(\\w+) # Hайти "слово" и сохранить его в $1
}{
no strict \'refs\';
if (defined $$1) {
$$1; # Расширять только глобальные переменные
} else {
"[NO VARIABLE: \\$$1]; # Сообщение об ошибке
} }еgх;
Обратите внимание на изменение синтаксиса $$1 в Perl 5.004; когда-то
это выражение означало ${$}!, а теперь оно означает ${$1}. Для
обеспечения обратной совместимости в строках оно сохраняет старый
смысл (но выдаёт предупреждение с -w). Запись ${$1} используется в
строках для того, чтобы предотвратить разыменование PID. Если значение
$$ равно 23448, то $$1 в строке превращается в 234481, а не в значение
переменной, имя которой хранится в $1.
===