Perl Regex 'e' (eval) модификатор с s///
У меня небольшая проблема с пониманием этого простого использования модификатора /e regex.
my $var = 'testing';
$_ = 'In this string we are $var the "e" modifier.';
s/(\$\w+)/$1/ee;
print;
Возвращает: "В этой строке мы тестируем модификатор" e ".
Я не понимаю, почему нужны два модификатора 'e'. Насколько я вижу, $1 должен захватить '$ var' из строки, и один модификатор 'e' должен затем заменить переменную своим значением. Однако я должен что-то недопонимать, так как попытка использования вышеуказанного кода одним модификатором 'e' не заметно заменяет ничего в строке.
Извините, что задал такой простой вопрос!
Спасибо.
Ответы
Ответ 1
Это не совсем "простой" вопрос, поэтому не бейте себя.
Проблема заключается в том, что с одним /e
под RHS понимается код, результат eval
d которого используется для замены.
Что такое RHS? Его $1
. Если вы оценили $1
, вы обнаружите, что содержит строку $var
. Он не содержит содержимое указанной переменной, просто $
, за которой следует v
, за которым следует a
, а затем r
.
Поэтому вы должны его дважды оценить, чтобы превратить $1
в $var
, а затем снова включить предыдущий результат $var
в строку "testing"
. Вы делаете это с помощью двойного модификатора ee
в s
.
Вы можете проверить это довольно легко, запустив его с одним /e
против двух из них. Heres demo a both, плюс третий способ, который использует символическое разыменование - который, поскольку он ссылается на таблицу символов пакета, работает только с переменными пакета.
use v5.10;
our $str = q(In this string we are $var the "e" modifier.);
our $var = q(testing);
V1: {
local $_ = $str;
s/(\$\w+)/$1/e;
say "version 1: ", $_;
}
V2: {
local $_ = $str;
s/(\$\w+)/$1/ee;
say "version 2: ", $_;
}
V3: {
no strict "refs";
local $_ = $str;
s/\$(\w+)/$$1/e;
say "version 3: ", $_;
}
При запуске создается:
version 1: In this string we are $var the "e" modifier.
version 2: In this string we are testing the "e" modifier.
version 3: In this string we are testing the "e" modifier.
Ответ 2
Чтобы быть ясным, форма s//ee
не модифицирует ваш шаблон регулярного выражения или интерпретацию регулярного выражения вообще. Это необязательная обработка заменяемой боковой строки после выполнения регулярного выражения. (См. PERLOP Regex Quote-like operator)
e
или ee
просто смешиваются с опциями регулярного выражения PATTERN в форме s/PATTERN/REPLACEMENT/msixpodualgcer
.
От Perlop:
Параметры такие же, как и для m//с добавление следующей замены конкретные варианты:
e Evaluate the right side as an expression.
ee Evaluate the right side as a string then eval the result.
r Return substitution and leave the original string untouched.
Вы можете видеть то же поведение типа e
vs ee
в ситуациях без регулярных выражений, как показано в этом примере:
#!/usr/bin/perl
use warnings;
use strict;
my $var = "var contents";
my $str='"-> $var <-"';
print eval('$str'), "\n"; # equivalent to s//e
print eval(eval('$str')), "\n"; # equivalent to s//ee
Вывод:
"-> $var <-"
-> var contents <-
Ответ 3
Попробуйте утилиту переименования из последнего пакета perl с помощью:
rename -v 's/\b(\w)/uc($1)/eg' *
Здесь шаблон \b
находит границу слова, а модификатор e
позволяет оценивать в подстановке, а g
заменяет все вхождения.
Вы также можете переименовать в camelCase с помощью:
rename -v 's/\b(\w)/uc($1)/eg' *
rename -v 's/^(\w)/lc($1)/e' *
rename -v 's/\s+//g' *