waldner has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to understand this:
$ perl -We '$_="I have 10 dollars.\n"; s/(10)/$1/; print;' I have 10 dollars. $ perl -We '$_="I have 10 dollars.\n"; s/(10)/$1+1/; print;' I have 10+1 dollars. $ perl -We '$_="I have 10 dollars.\n"; s/(10)/$1+1/e; print;' I have 11 dollars.
Up to this, everything as expected. But now:
$ perl -We '$_="I have 10+4 dollars.\n"; s/(10\+4)/$1/; print;' I have 10+4 dollars. $ perl -We '$_="I have 10+4 dollars.\n"; s/(10\+4)/$1/e; print;' I have 10+4 dollars. $ perl -We '$_="I have 10+4 dollars.\n"; s/(10\+4)/$1/ee; print;' I have 14 dollars.
What I don't understand is why, in the second case, the first and second outputs are the same, and thus I need two /ee to have the expression evaluated. After all, $1 is already "10+4", so a single /e should be enough to evaluate it.

I'm surely missing something here. Thanks for any help.

Replies are listed 'Best First'.
Re: /e in regexes
by ikegami (Patriarch) on Jun 22, 2008 at 16:33 UTC

    The "e" being absent means "treat the replace expression as a double-quote string literal".

    $x = '10+4'; print( "$x" ); # 10+4, not 14

    The "e" being present means "treat the replace expression as a Perl expression".
    The Perl expression $1 evaluates to the value of $1, which is the string 10+4.

    $x = '10+4'; print( $x ); # 10+4, not 14

    s/.../.../ee is an awful* way of saying s/.../eval .../e.
    That means that not only is $1 treated as a Perl expression, so is the value returned by it.

    $x = '10+4'; print( eval $x ); # 14

    * — In my opinion, something as dangerous as eval EXPR shouldn't be hidden as an simple little "e".

    Update: Added illustrative code.

      Thanks. But why a single /e is enough in the first case then?
        Because in this cases the evaluated string is "10" + 1, which forces perl to treat "10" as a number. If your evaluated string is "10+1", The whole thing is taken as a string literal.

        In one case, you want the replacement expression to be a Perl expression,
        In the other, you want the value of $1 to be evaluated.

        # s/(10)/$1+1/e $dollar1 = "10"; $replace = $dollar1 + 1; # One 'e', so Perl expression. print $replace; # 11 # s/(10\+4)/$1/e $dollar1 = "10+4"; $replace = $dollar1; # One 'e', so Perl expression. print $replace; # 10+4 # s/(10\+4)/$1/ee $dollar1 = "10+4"; $replace = eval $dollar1; # Two 'e', so Perl expression + eval. print $replace; # 14

        Update: Oops, this was supposed to be a reply to Re^2: /e in regexes.

Re: /e in regexes
by shmem (Chancellor) on Jun 22, 2008 at 16:44 UTC

    The /e switch treats the replacement as an expression to be executed. This is not the same as evaluating the contents of $1..$n as executable code, i.e. treating the result of the interpolation as executable code, which needs "double eval" (/ee).

    You could re-write

    s/(10\+4)/$1/ee;

    as

    s/(10\+4)/eval $1/e;

    In the case of s/(10\+4)/$1/e the replacement just resolves as the code line

    "10+4";

    which yields a string upon execution.

    update: added single /e explanation

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: /e in regexes
by Fletch (Bishop) on Jun 22, 2008 at 16:37 UTC

    Think of it this way:

    No /e means the right hand side of the s/// is a double quoted string. One makes the right hand side an expression and the result of evaluating that expression is the substituted value. Two makes the right hand side a string eval and the return from that is the right side.

    Your first and second case are the equivalent of "$1" and $1 respectively, which since $1 contains the string value '10+4' works out to the same thing. The last is eval "$1" which actually does what you're expecting from the second.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: /e in regexes
by pc88mxer (Vicar) on Jun 22, 2008 at 17:34 UTC
    Here's another thread which might help explain things: Regular expression "replace string interpolation" problem.

    What confuses a lot of people is that when the replacement is a simple expression like $that, the following are equivalent:

    s/$this/$that/; s/$this/$that/e;
    However, note how this changes when the replacement varies just a little:
    # these are are equivalent: s/$this/some text/; s/$this/"some text"/e; # and so are these: s/$this/$that was close/; s/$this/$that." was close"/e;