Perl Regex 'e' (eval) модификатор с s /// - PullRequest
31 голосов
/ 21 мая 2011

У меня небольшие проблемы с пониманием этого простого использования модификатора / 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' явно не заменяет ничего в строке.

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

Спасибо.

Ответы [ 3 ]

39 голосов
/ 21 мая 2011

Это не совсем «простой» вопрос, так что не мучайте себя.

Проблема в том, что с одним /e RHS понимается как код, для которого eval 'dрезультат используется для замены.

Что это за RHS?Это $1.Если вы оценили $1, вы обнаружите, что содержит строку $var.Он не содержит содержимого указанной переменной, просто $, за которым следует v, затем a и r.

Поэтому вы должны оценить его дважды, один раз, чтобы превратить $1 в $var, затем снова, чтобы превратить предыдущий результат $var в строку "testing".Это можно сделать, применив модификатор double ee к оператору s .

. Вы можете легко проверить это, запустив его с одним /e против двух из них.Вот демонстрационный пример обоих, плюс третий способ, который использует символьную разыменование - который, поскольку он ссылается на таблицу символов пакета, работает только с переменными пакета.

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.
9 голосов
/ 21 мая 2011

Для ясности, форма s//ee не изменяет ваш шаблон регулярного выражения или интерпретацию регулярного выражения вообще.Это необязательная обработка замещающей боковой строки после выполнения регулярного выражения.(См. PERLOP Regex-подобные операторы )

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 против ee в ситуациях, не связанных с регулярными выражениями, как показано в этом примере:

#!/usr/bin/perl 
use warnings;
use strict;

my $var = "var's contents";
my $str='"-> $var <-"';
print eval('$str'), "\n";        # equivalent to s//e
print eval(eval('$str')), "\n";  # equivalent to s//ee

Вывод:

"-> $var <-"
-> var's contents <-
0 голосов
/ 02 июня 2015

Попробуйте утилиту переименования из последнего пакета 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' *
...