Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re: /ee -> Use of uninitialized value in substitution iterator (without back references)

by haukex (Bishop)
on Apr 29, 2021 at 15:14 UTC ( #11131880=note: print w/replies, xml ) Need Help??


in reply to /ee -> Use of uninitialized value in substitution iterator (without back references)

As per Regexp Quote Like Operators, /ee means "Evaluate the right side as a string then eval the result." and "A /e will cause the replacement portion to be treated as a full-fledged Perl expression and evaluated right then and there. It is, however, syntax checked at compile-time. A second e modifier will cause the replacement portion to be evaled before being run as a Perl expression."

So basically, "$rhs" becomes qqq, which when evaled causes an error: Try adding print $@ to your code and you'll see Bareword "qqq" not allowed while "strict subs" in use at (eval 1) line 1., so eval is returning undef which is causing the Use of uninitialized value in substitution iterator.

Running perl -e 'print eval("qqq");' prints qqq.

That's because that's not using strict - perl -wMstrict -e 'print eval("qqq"); print $@;' prints Bareword "qqq" not allowed while "strict subs" in use at (eval 1) line 1.

And of course there's no warning with just /e instead of /ee; in the real program, I need /ee.

Perhaps your example is a little too abstracted from the original program? Needing /ee is somewhat rare in my experience. Could you show a more representative example of why you (think you) need it, perhaps we can come up with a better solution?

  • Comment on Re: /ee -> Use of uninitialized value in substitution iterator (without back references)
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: /ee -> Use of uninitialized value in substitution iterator (without back references)
by karlberry (Novice) on Apr 29, 2021 at 17:50 UTC

    Thanks to both of you for your replies. That all makes sense. It was the "substitution iterator" that threw me off the track. I should have thought to check $@ ...

    As for why /ee. I agree it's unusual. I'd used Perl for some 30 years before I had occasion to do so, and there may well be a better way to do it. My goal is to specify regexp substitutions in an external file, but just as strings, not Perl code to be executed, for consistency with other parts of the program and also so I could track whether a given substitution was performed. For example, I need to remove braces from around strings (I'm not concerned about unmatched braces), so the data file has this line, separating lhs and rhs with || (arbitrary):

    \{(.*?)\}||$1
    

    I read the data file, split each line into the lhs and rhs, add to lists @lhs and @rhs. Then, to apply the substitutions to the input, I loop through the lists:

    $str = "whatever input";
    ...
    for (my $i = 0; $i < @$lhs; $i++) {
      my $lhs = $lhs->$i;
      my $rhs = $rhs->$i;
      eval { $str =~ s/$lhs/$rhs/eeg; }; # yet one more eval!
      $@ && die "eval(s/$lhs/$rhs/eeg) failed: $@";
      # ... more irrelevant stuff ...
    }
    

    This crazy "triple eval" was only way I found to apply the substitution with lhs and rhs stored in variables. From what we've already discussed, I guess adding single quotes will change things. Anyway, if a simpler way in general comes to mind, I'd be glad to hear about it. Thanks.

    P.S. I see now that I should also be checking $@ inside the eval, to see if there were errors from the /ee.

      If you require the $rhs to always be a Perl expression, then /ee works fine for me with these two examples. The $rhs in your example from the root node just needs to be adjusted to '"qqq"' so it's a valid Perl expression.

      use warnings; use strict; use Test::More tests=>2; { my $lhs = '\\{(.*?)\\}'; my $rhs = '$1'; my $str = '{abc}'; $str =~ s{$lhs}{$rhs}ee; is $str, 'abc'; } { my $lhs = 'xyz'; my $rhs = '"qqq"'; my $str = 'AxyzB'; $str =~ s{$lhs}{$rhs}ee; is $str, 'AqqqB'; }
      P.S. I see now that I should also be checking $@ inside the eval, to see if there were errors from the /ee.

      Note Bug in eval in pre-5.14 - if I wanted to play it really safe, I might do use warnings FATAL => 'uninitialized'; just before the s///ee to make certain errors in the eval propagate.

      (BTW, please use <code> tags to format your code)

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (1)
As of 2021-07-31 23:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?