perl运营商/// e没有按预期工作

时间:2016-11-15 12:37:49

标签: regex perl syntax

我正在试图弄清楚这是为什么有效:

 $_='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的行为应该相同,但显然我错了。

我错过了什么?

1 个答案:

答案 0 :(得分:7)

您误解了表达式修饰符 - 单个/e

它会将替换字符串视为Perl表达式,并且本质上是标准模式的替代方法,它将处理字符串,就好像它是双引号一样

通常

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

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

生成等效于字符串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表达式。无法执行从目标字符串的某些部分构造的任意Perl代码,而无需添加第二个/e修饰符,代表 eval

结果/ee导致Perl将替换视为表达式(而不是对其进行双引号插值),然后 eval 结果为表达

例如

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

首先评估表达'$x' . $2 . $2的{​​{1}}表达式,然后对该字符串执行$x++,返回1(因此原始的eval将替换为12+34)并递增1

如果您可以编写满足您需要的Perl表达式,则可以将表达式模式与单个$x一起使用。否则,您需要使用/e来获取 eval 阶段

如果您完全涉及/ee,我认为使用大括号会更清楚。这样它看起来像Perl代码而不是字符串替换

/e