Подтвердить что ты не робот

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' не заметно заменяет ничего в строке.

Извините, что задал такой простой вопрос!

Спасибо.

4b9b3361

Ответ 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' *