Reputation: 12012
I'm trying to figure out why this is working :
$_='12+34';$x=1;
s/(\d+)(.)(\d+)/"\$x$2$2"/ee; # This is working, does $x++
print "x=$x \n"; # x=2
while this is not :
$_='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?)
I have the guts that s/xxx/yyy/e
and s/xxx/"yyy"/ee
should behave the same, but obviously I'm wrong.
What am I missing ?
Upvotes: 0
Views: 220
Reputation: 126742
You're misunderstanding the expression modifier -- a single /e
It causes the replacement string to be treated as a Perl expression, and is essentially an alternative to the standard mode, which is to process the string as if it were in double-quotes
Normally
my $x = 1;
my $y = '12+34';
$y =~ s/(\d+)(.)(\d+)/\$x$2$2/;
produces a replacement equivalent to the string qq{\$x$2$2}
, which is $x++
If you add an /e
then the replacement is treated as a Perl expression, and you are getting errors because \$x$2$2
isn't valid Perl. You could get the same result as before by using
s/(\d+)(.)(\d+)/'$x' . $2 . $2/e
or, as you have seen, the string expression
s/(\d+)(.)(\d+)/"\$x$2$2"/e
But all these do is evaluate the Perl expression. There is no way to execute arbitrary Perl code that is constructed from parts of the target string without adding a second /e
modifier which stands for eval
The resulting /ee
causes Perl to treat the replacement as an expression (instead of doing double-quote interpolation on it) and then eval the result of that expression
For instance
s/(\d+)(.)(\d+)/'$x' . $2 . $2/ee
first evaluates the expression '$x' . $2 . $2
giving $x++
and then does eval
on that string, returning 1 (so the original 12+34
is replaced with 1
) and incrementing $x
You can use expression mode with a single /e
if you can write a Perl expression that does what you need. Otherwise you need to use /ee
to get an eval stage as well
I think it's clearer to use braces if you involve /e
at all. That way it looks like Perl code and not a string replacement
s{(\d+)(.)(\d+)}{
'$x' . $2 . $2
}ee
Upvotes: 7