Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

"ee" in Regular Expression: version issue?

by Anonymous Monk
on Dec 03, 2012 at 19:02 UTC ( [id://1006930]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all! At work, I'm writing a script that uses a configuration file of strings that are converted to regular expressions. I have my script working for matching, but it breaks for substitution. For example, the string to match to might look like

 $lhs = (\d*?)-(.*?)-(.*)

and the right hand side (for substitution looks like:

 $rhs = $1$2$3

I'm using the code likes this:

 $var =~ s/$lhs/$rhs/ee

If I run it like above, I get an error message:

Scalar found where operator expected at (eval 1) line 1, near "$1$" (Missing operator before $?) Scalar found where operator expected at (eval 1) line 1, near "$2$" (Missing operator before $?)

I've also tried with a single "e" or no "e"s at all, and just get this for the value of $var: $1$2$3

For the test case that I'm passing into this regular expression, it is matching properly and all the capture groups are capturing ( I had it print out the values of $1, $2, $3 and it gave me the expected output correctly )

This is running on a server at work that has Perl v5.8.8 installed on it. Unfortunately, the decision to upgrade it is not mine, although discussions have been started once I raised it as a concern. Is the age of this Perl install the problem, or am I missing something else?

Thanks in advance for any assistance!

Replies are listed 'Best First'.
Re: "ee" in Regular Expression: version issue?
by Kenosis (Priest) on Dec 03, 2012 at 19:52 UTC

    Try concatenating the vars for use in the substitution:

    use strict; use warnings; my $lhs = '(\d*?)-(.*?)-(.*)'; my $rhs = '$1.$2.$3'; while ( my $var = <DATA> ) { chomp $var; $var =~ s/$lhs/$rhs/ee; print $var, "\n"; } __DATA__ 123-456-789 -456-789 789

    Output:

    123456789 456789 789

    From the error message, it appears that the results of the first evaluation is ambiguous to the interpreter when it attempts to evaluate it without the concatenation operator.

      Or use straight interpolation: my $rhs = '"$1$2$3"';. The key here is that the string literal present after the initial eval (which subs $rhs to its value) is valid Perl code.


      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

        Yes, excellent. Perhaps the enclosing double-quotes (also) helps to disambiguate the expression. After the first eval, the interpreter sees this:

        $var =~ s/(\d*?)-(.*?)-(.*)/$1$2$3/ee;

        The substituting expression is problematic w/o either being interpolated via "$1$2$3" or concatenated using $1.$2.$3.

Re: "ee" in Regular Expression: version issue?
by ikegami (Patriarch) on Dec 04, 2012 at 11:38 UTC
    $var =~ s/$lhs/$rhs/ee;
    means
    $var =~ s/$lhs/eval $rhs/e;
    (Except that exceptions aren't caught.)

    That means $rhs must contain valid Perl code, yet $1$2$3 is not valid Perl code. "$1$2$3" or $1.$2.$3 would be valid Perl code, so you want

    $rhs = '"$1$2$3"';
    or
    $rhs = '$1.$2.$3';
s/RegEx/substitutions/: Variable interpolation and when to use /e - modifiers
by LanX (Saint) on Dec 04, 2012 at 18:58 UTC
    Let me try to write a deeper conceptional answer, because the handling of /e irritated me for long and I need to pin down the source of this irritation myself.

    The short answer

    The RHS of s/LHS/RHS/ undergoes a variable interpolation (like doublequotes) if and only if there are no /e modifiers used.

    modifiers substition equivalent
    no e VAR =~ s/LHS/RHS/ VAR =~ m/LHS/; MATCH = "RHS"
    one e VAR =~ s/LHS/RHS/e VAR =~ m/LHS/; MATCH = eval 'RHS'
    two e VAR =~ s/LHS/RHS/ee VAR =~ m/LHS/; MATCH = eval eval 'RHS'
    more e Don't! Only for brainfuck and obfuscation, better call function

    MATCH meaning the substring from VAR matching the LHS-pattern.

    For completeness nota bene ...

    concept code equivalent
    disabling interpolation VAR =~ s'LHS'RHS' VAR =~ m/LHS/; MATCH = 'RHS'
    string interpolation $a = "$b - $c" $a = $b . ' - ' . $c
    variable evaluation $a = $b $a = eval '$b'

    The long answer ...

    Problem

    At first it's confusing that there is no difference between s/(pattern)/$1/ and s/(pattern)/$1/e

    example:

    DB<1> $_='abc'; s/a(b)c/$1/; print $_ b DB<2> $_='abc'; s/a(b)c/$1/e; print $_ b

    Explanation

    Line 1 w/o e-modifier but with interpolation:

    Variables in RHS undergo an interpolation like the result in double-quotes "RHS"!

    the following code is equivalent

    DB<1> $_='abc'; s/a(b)c/$1/; print $_ b DB<3> $_='abc'; m/a(b)c/; $_ = "$1" ; print $_ b

    Line 2: with e-modifier but w/o interpolation:

    RHS is evaluated without variable interpolation¹ like in simple quotes eval 'RHS'

    DB<2> $_='abc'; s/a(b)c/$1/e; print $_ b DB<4> $_='abc'; m/a(b)c/; $_= eval '$1'; print $_ b

    And $_= eval '$1' just means $_= $1

    I hope now double evals /ee can be better understood

    Like ikegami stated correctly those  s/LHS/RHS/ee; and  s/LHS/eval RHS/e; are equivalent

    Those double /ee are used if you need a matchvariables (a substring from LHS) to be interpolated within an eval, b/c variable interpolation is missing!

    Any code from LHS will be treated as uninterpolated string, as in these equivalent expamples

    DB<5> $_='warn 666'; s/(.*)/$1/e; print $_ warn 666 DB<6> $_='warn 666'; m/(.*)/; $_= eval '$1'; print $_ warn 666

    So if I need code-evaluation from parts of LHS I need a second /e

    DB<7> $_='warn 666'; s/(.*)/$1/ee; print $_ 666 at (eval 171) .... # skipped error message 1 # $_ = return code from warn DB<8> $_='warn 666'; m/(.*)/; $_= eval eval '$1'; print $_ 666 at (eval 175). ... # skipped error message 1 # $_ = return code from warn

    Resumee

    I think this explanation could be better worded ...

    It already helped me a lot to clarify whats happening and I hope it helps you too or anyone else who tries to explain it better. =)

    Cheers Rolf

    1) As a side note:

    Variable interpolation is a powerful tool which allows some (not all) "evaluation like effects" like interpolation of hash-variables.

    DB<134> $hash{b}=666; DB<135> $_='abc'; s/a(b)c/$hash{$1}/; print $_ 666 DB<136> $_='abc'; m/a(b)c/; print "$hash{$1}"; 666

Re: "ee" in Regular Expression: version issue?
by Anonymous Monk on Dec 03, 2012 at 19:32 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1006930]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (7)
As of 2024-03-28 19:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found