2016-11-15 75 views
0

我试图找出为什么这是工作:Perl的操作符/// G未按预期

$_='12+34';$x=1; 
s/(\d+)(.)(\d+)/"\$x$2$2"/ee; # This is working, does $x++ 

print "x=$x \n";    # x=2 

虽然这不是:

$_='12+34';$x=1; 
s/(\d+)(.)(\d+)/\$x$2$2/e; # This is NOT working 

# Error message is : 
# Scalar found where operator expected at ./test.pl line 2, near "$x$2" 
#  (Missing operator before $2?) 

我有胆量说s/xxx/yyy/es/xxx/"yyy"/ee应该表现相同,但显然我错了。

我缺少什么?

回答

7

你误解表达改性剂 - 单个/e

它使替换串被视为一个Perl表达,并且是基本上为标准模式的替代,这是为了处理字符串就好像它是用双引号

通常

my $x = 1; 
my $y = '12+34'; 

$y =~ s/(\d+)(.)(\d+)/\$x$2$2/; 

产生replacem耳鼻喉科等价的字符串qq{\$x$2$2},这是$x++

如果添加/e则替换被视为一个Perl的表达,你得到错误,因为\$x$2$2是无效的Perl。您可以通过使用

s/(\d+)(.)(\d+)/'$x' . $2 . $2/e 

像以前一样得到同样的结果,或如你所看到的,字符串表达式

s/(\d+)(.)(\d+)/"\$x$2$2"/e 

但是,所有这些要做的就是评估Perl的表达。没有办法在不添加第二/e改性剂,其代表EVAL

所得/ee导致Perl来对待替换作为表达以执行从目标串的部分构成任意Perl码(代替这样做就可以了双引号插值),然后EVAL表达式的结果

例如

s/(\d+)(.)(\d+)/'$x' . $2 . $2/ee 

首先计算表达式'$x' . $2 . $2$x++,然后做eval该字符串,返回1(这样原12+34替换1)和递增$x

您可以使用表达模式单一/e如果你可以写一个Perl表达式,可以满足你的需求。否则,你需要使用/ee得到一个EVAL阶段以及

我认为这是更清楚,如果你涉及/e在所有使用大括号。这样它看起来像Perl代码而不是字符串替换

s{(\d+)(.)(\d+)}{ 
    '$x' . $2 . $2 
}ee 
+0

Correcto !! '/ ee' double评估RHS – 2016-11-15 13:33:54

+1

@Gerry:*错误!*我竭尽全力解释第一个'/ e'将替换视为*表达式*。它不会“评估”任何东西。第二个'/ e'将'eval'表达式的值 – Borodin

+0

完美答案。现在更清楚了。我错过了替换部分嵌入在使用/// e修饰符时不存在的不可见qq {...}的事实。谢谢。 –