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

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.

  • Comment on Re^2: /ee -> Use of uninitialized value in substitution iterator (without back references)

Replies are listed 'Best First'.
Re^3: /ee -> Use of uninitialized value in substitution iterator (without back references)
by haukex (Archbishop) on Apr 29, 2021 at 18:11 UTC

    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)