带有s //的Perl Regex'e'(eval)修饰符

时间:2011-05-21 14:03:12

标签: regex perl modifier

我在理解这个简单使用/ e正则表达式修饰符方面遇到了一些麻烦。

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

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

print;

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

我看不出为什么需要两个'e'修饰符。据我所知,$ 1应该从字符串中捕获'$ var',然后单个'e'修饰符应该能够用它的值替换变量。但是我必须误解一些东西,因为只用一个'e'修饰符来尝试上面的代码并不能明显地替换字符串中的任何内容。

请问这么简单的问题!

感谢。

3 个答案:

答案 0 :(得分:39)

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

问题在于,使用单个/e时,RHS被理解为使用eval d结果进行替换的代码。

什么是RHS?它是$1。如果您评估了$1,则会发现其中包含字符串 $var。它不包含所述变量的内容,只有$后跟v后跟a后跟r

因此,您必须对其进行两次评估,一次将$1评估为$var,然后再将$var的上一个结果转换为字符串"testing"。您可以通过s operator上的双ee修饰符来实现此目的。

您可以通过使用一个/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.

答案 1 :(得分:8)

要明确,s//ee表单根本不会修改正则表达式或正则表达式解释。在执行正则表达式之后,它是替换侧弦的可选处理。 (见PERLOP Regex Quote-like operators

eee只是混合到s/PATTERN/REPLACEMENT/msixpodualgcer表格中的PATTERN侧正则表达式选项中。

来自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'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 <-

答案 2 :(得分:0)

尝试使用最新的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' *