Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re: variables in substition/eval

by kcott (Archbishop)
on Aug 18, 2017 at 06:33 UTC ( [id://1197594]=note: print w/replies, xml ) Need Help??


in reply to variables in substition/eval

G'day xaphod,

[Assumption: As already stated, you need to tell us what you do expect, not just that you didn't get what you expected. I'm assuming that, in the three blocks of output, you want "huey & donald", "dewey & donald" and "louis & donald", respectively.]

AM has already pointed out the issue. In Perl v5.14, non-destructive substitution was introduced, which could get around this problem (see "perl5140delta: Non-destructive substitution" for details and additional information).

It looks like you've probably over-engineered your solution and, as result, generated the unexpected output. Your nested loops could have been written like the following: I've commented out all the over-engineered code so you can see how much simpler it could have been.

foreach my $who (@list) { #my $sub = "\$ln =~ s/scrooge (& donald)/$who \$1/g;"; print "$who\n"; foreach my $ln (@lines) { #eval $sub; #print "$ln\n"; print $ln =~ s/scrooge (& donald)/$who $1/r, "\n"; } print "\n"; }

That produces the output as per my "Assumption".

If your version of Perl is older than 5.14, which is now over six years old[perlhist], consider upgrading but, for now, you'll need to code this the old way by assigning the original text to a new variable first, then performing the substitution on that new variable, leaving the original unchanged.

By the way, in your original regex, you used the 'g' modifier. This is completely unnecessary: it's for performing multiple matches in a single regex; not for single matches that happen to be performed on multiple occasions. These three one-liners should show the difference:

$ perl -E 'my $x = "AAA"; $x =~ s/A/B/; say $x' BAA $ perl -E 'my $x = "AAA"; $x =~ s/A/B/ for 0 .. length($x) - 1; say $x +' BBB $ perl -E 'my $x = "AAA"; $x =~ s/A/B/g; say $x' BBB

That's just a guess as to why you thought you needed a 'g' modifier. See "perlre: Modifiers" for details.

— Ken

Replies are listed 'Best First'.
Re^2: variables in substition/eval
by AnomalousMonk (Archbishop) on Aug 18, 2017 at 12:55 UTC

    In a situation like this, my own preference is to use look-arounds to avoid capturing (and substituting back) more than necessary (tested under 5.8.9):

    c:\@Work\Perl\monks>perl -wMstrict -le "my @lines = ( 'Once upon a time', 'scrooge & donald', 'went for a long walk', ); ;; my @list = qw(huey dewey louis); ;; foreach my $who (@list) { print qq{who '$who'}; foreach my $ln (@lines) { (my $newln = $ln) =~ s{ scrooge (?= \s+ & \s+ donald) }{$who}xmsg +; print qq{ '$newln'}; } } " who 'huey' 'Once upon a time' 'huey & donald' 'went for a long walk' who 'dewey' 'Once upon a time' 'dewey & donald' 'went for a long walk' who 'louis' 'Once upon a time' 'louis & donald' 'went for a long walk'


    Give a man a fish:  <%-{-{-{-<

      My intention was to show the use of the 'r' modifier to resolve the problem. Because 'r' may have appeared to replace 'g', I commented on that also.

      Not commenting on other aspects of the code should not be construed as tacit approval. I still don't know what output was expected; I don't know the context of this code; and there are other unknowns, such as how "scrooge" relates to the anything here.

      There are in fact all sorts of issues with the code, ranging from poorly named variables (e.g. @list) to bad grammar (e.g. non-capitalised proper nouns).

      I possibly would have used an easily identifiable placeholder such that the regex required no captures or lookaround assertions. The substitution may simply have been something like:

      ... s/__NEPHEW__/$nephew/r ...

      Update: Did Donald Duck have a relative named Scrooge? Perhaps that explains the "scrooge" connection. Still just guessing. :-)

      — Ken

        Donald does indeed have a relative named Scrooge: his uncle, Scrooge McDuck, a notoriously penny-pinching millionaire! At some point, the Duck family of the McDuck clan apparently changed their surname, but I ran out of interest before I could pin down the precise genealogy.


        Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

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

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

    No recent polls found