我正在试图弄清楚这是为什么有效:
$_='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/e
和s/xxx/"yyy"/ee
的行为应该相同,但显然我错了。
我错过了什么?
答案 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