32

我在理解 /e 正则表达式修饰符的这种简单用法时遇到了一些麻烦。

my $var = 'testing';
$_ = 'In this string we are $var the "e" modifier.';

s/(\$\w+)/$1/ee;

print;

返回:“在这个字符串中,我们正在测试“e”修饰符。”

我不明白为什么需要两个“e”修饰符。据我所见,$1 应该从字符串中捕获 '$var',然后单个 'e' 修饰符应该能够用它的值替换变量。但是,我一定是误解了一些东西,因为仅使用一个 'e' 修饰符尝试上述代码不会明显替换字符串中的任何内容。

原谅我问了这么简单的问题!

谢谢。

4

3 回答 3

39

这不是一个“简单”的问题,所以不要自责。

问题在于,对于单个/e, RHS 被理解为其eval'd 结果用于替换的代码。

那个 RHS 是什么?是$1。如果您进行了评估$1,您会发现包含该字符串 $var。它不包含所述变量的内容,只是 $后跟 av后跟 ana后跟 an r

因此,您必须对其进行两次评估,一次$1变成$var,然后再次将之前的结果$var变成字符串"testing"。您可以通过在operatoree上使用 double修饰符来做到这一点。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.
于 2011-05-21T14:23:29.350 回答
9

需要明确的是,该s//ee表单根本不会修改您的正则表达式模式或正则表达式解释。它是执行正则表达式后对替换侧字符串的可选处理。(请参阅PERLOP Regex 引用式运算符

eoree只是混合到表单中的 PATTERN 端正则表达式选项中s/PATTERN/REPLACEMENT/msixpodualgcer

来自佩洛普:

选项与 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.

您可以在非正则表达式情况下看到相同的evsee类型行为,如本例所示:

#!/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 <-
于 2011-05-21T16:26:02.473 回答
-1

尝试使用最新的 perl 包中的重命名实用程序:

rename -v 's/\b(\w)/uc($1)/eg' *

在这里,pattern\b找到单词边界,e修饰符在替换中启用评估,并g替换所有出现。

您也可以使用以下方法重命名为 camelCase:

rename -v 's/\b(\w)/uc($1)/eg' *
rename -v 's/^(\w)/lc($1)/e' *
rename -v 's/\s+//g' *
于 2015-06-02T01:28:21.090 回答