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

pb1*_*149 31 regex perl modifier

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

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

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

print;
Run Code Online (Sandbox Code Playgroud)

返回:"在这个字符串中,我们正在测试"e"修饰符."

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

请问这么简单的问题!

谢谢.

tch*_*ist 39

这不是一个"简单"的问题,所以不要打败自己.

问题在于,单一/e的RHS被理解为代码,其eval结果用于替换.

什么是RHS?是的$1.如果您进行了评估$1,则会发现它包含字符串 $var.它不包含所述变量的内容, $后面v跟着一个a后跟一个r.

因此,你必须两次对其进行评估,一旦转$1$var,然后再次把以前的结果$var到字符串"testing".你可以通过ees运算符上使用double 修饰符来实现.

您可以通过一个/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: ", $_;
}
Run Code Online (Sandbox Code Playgroud)

运行时,会产生:

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.
Run Code Online (Sandbox Code Playgroud)

  • @ user761513:没有修饰符,`$ 1`作为替换文本用作字符串.使用单个`e`,它被用作表达式,具有完全相同的结果.要查看差异,请将`s/.../$ 1(hello)/`(一个字符串)与`s/.../uc($ 1)/ e`(表达式)进行比较. (3认同)
  • 具体来说,如果没有修饰符,替换文本的行为就像_double quoted_字符串。因此,“ $ 1”将插值到第一组括号所捕获的内容。 (2认同)

the*_*olf 9

要清楚,s//ee表单根本不会修改正则表达式或正则表达式解释.在执行正则表达式之后,它是替换侧弦的可选处理.(参见PERLOP Regex报价操作员)

eee刚刚获得混合到图案侧壁的正则表达式的选择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.
Run Code Online (Sandbox Code Playgroud)

您可以在非正则表达式情况下看到相同的evs 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
Run Code Online (Sandbox Code Playgroud)

输出:

"-> $var <-"
-> var's contents <-
Run Code Online (Sandbox Code Playgroud)