我试图弄清楚为什么这样做:
$_='12+34';$x=1;
s/(\d+)(.)(\d+)/"\$x$2$2"/ee; # This is working, does $x++
print "x=$x \n"; # x=2
Run Code Online (Sandbox Code Playgroud)
虽然这不是:
$_='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?)
Run Code Online (Sandbox Code Playgroud)
我有勇气s/xxx/yyy/e并且s/xxx/"yyy"/ee应该表现得一样,但显然我错了.
我错过了什么?
你误解了表达式修饰符 - 单个/e
它导致替换字符串被视为Perl表达式,并且本质上是标准模式的替代方法,它将处理字符串,就好像它是双引号一样
一般
my $x = 1;
my $y = '12+34';
$y =~ s/(\d+)(.)(\d+)/\$x$2$2/;
Run Code Online (Sandbox Code Playgroud)
产生等同于字符串的替换qq{\$x$2$2},即$x++
如果你添加一个/e然后替换被视为Perl表达式,并且你得到错误,因为\$x$2$2无效的Perl.您可以通过使用获得与以前相同的结果
s/(\d+)(.)(\d+)/'$x' . $2 . $2/e
Run Code Online (Sandbox Code Playgroud)
或者,正如您所见,字符串表达式
s/(\d+)(.)(\d+)/"\$x$2$2"/e
Run Code Online (Sandbox Code Playgroud)
但所有这些都是评估Perl表达式.没有办法执行从目标字符串的部分构造的任意Perl代码而不添加/e代表eval的第二个修饰符
结果/ee导致Perl将替换视为表达式(而不是对其进行双引号插值)然后评估该表达式的结果
例如
s/(\d+)(.)(\d+)/'$x' . $2 . $2/ee
Run Code Online (Sandbox Code Playgroud)
首先计算表达式'$x' . $2 . $2给出$x++,然后eval对该字符串进行计算,返回1(因此原始12+34替换为1)并递增$x
如果您可以编写满足您需要的Perl表达式,则可以将表达式模式与单个表达式一起使用/e.否则你也需要用来/ee获得一个eval阶段
如果您参与其中/e,我认为使用牙箍更清楚.这样它看起来像Perl代码而不是字符串替换
s{(\d+)(.)(\d+)}{
'$x' . $2 . $2
}ee
Run Code Online (Sandbox Code Playgroud)