Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

s/// operator and undef question...

by ismail (Acolyte)
on Dec 13, 2000 at 05:00 UTC ( [id://46358]=perlquestion: print w/replies, xml ) Need Help??

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

I found a bit of code in fooling around today:

my $target = 'this is a test of the servise'; for my $is ($target =~ /is/) { $target =~ s//are/; } print "$target\n"; # yields "thare are a test of the servaree'

What is going on here? I can only wildly speculate on the relationship... is this an acceptable way of doing things? Obsfucated?

Ismail

Replies are listed 'Best First'.
Re: s/// operator and undef question...
by merlyn (Sage) on Dec 13, 2000 at 05:30 UTC
    It took me a few minutes to see why it's working, and why you can't use it in general.
    1. You are likely missing a /g on the end of that regex match.
    2. What's happening is that $is is getting set to a list of two items, causing the loop to execute twice. The two values are ignored for the next step though.
    3. Since the last regex computed is is, that makes the substitute inside the loop work as if you had said $target =~ s/is/are/. Yup. Always scanning from the left.
    So, the only reason this works is because the replacement string cannot once again match the search string. But try it with s/is/iis/, and you'll be totally hosed.

    -- Randal L. Schwartz, Perl hacker

Re: s/// operator and undef question...
by chromatic (Archbishop) on Dec 13, 2000 at 05:25 UTC
    I can answer the first for you. m// matches the nothing at any part of the string:
    my $target = 'this is a test of the servise'; $target =~ s//are/; print "$target\n";
    There's a spot of nothing at the very start of the string.

    I think you're missing /g at the end of the regex in the loop condition. As for that, my assumption is that there's Deep Magic here, and you shouldn't rely on these results.

    Another test:

    if ($target =~ /test/) { $target =~ s//quiz/; }
    Maybe a blank regex condition on the left stays with what was previously matched. Dunno if that's an intended feature or not.

    Update: I'm upgrading it to potential bug:

    my $target = 'this is a test of the servise'; if ($target =~ /test/) { $target =~ s//test2/; } if ($target =~ /nothing/) { $target = s//null/; } else { $target =~ s//foo/; }
    The moral of the story is, don't do a substitution inside a match on the same string.
      my $target = 'this is a test of the servise'; if ($target =~ /test/) { $target =~ s//test2/; } if ($target =~ /nothing/) { $target = s//null/; } else { $target =~ s//foo/; }
      My guess is that this returns this is a foo2 of the servise as documented in perlop:
      [....] If the pattern evaluates to the empty string, the last successfully executed regular expression is used instead. [....]
      And so my standard admonition about "don't use $1 except in the context of a conditional" would also apply here, since "most recent success" is contextual.

      -- Randal L. Schwartz, Perl hacker

s/// tomfoolery explained (again)
by japhy (Canon) on Dec 13, 2000 at 06:42 UTC
    Ok, regardless of what is happening, merlyn explained the situation.
    $string =~ /foo/; $string =~ //; # this repeats the last successful match $string =~ /foo/; $string =~ s//bar/; # again, /foo/ is used in place of //


    japhy -- Perl and Regex Hacker
(Ovid) Re: s/// operator and undef question...
by Ovid (Cardinal) on Dec 13, 2000 at 05:29 UTC
    I could only duplicate your results with adding /g to the first regex. I have no frickin' clue how the substitution works. Incidentally, the following is a no-op:
    for ($target =~ /is/g) { s//are/; }
    But if I take of the /g switch:
    for ($target =~ /is/) { s//are/; }
    I get the following error message:
    Modification of a read-only value attempted at eval.pl line 6.
    This is beginning to look like a bug to me.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: s/// operator and undef question...
by Fastolfe (Vicar) on Dec 13, 2000 at 05:34 UTC
    Your expression $target =~ /is/ in a list context will return (1) for success (see m// in perlop). Thus, your loop is equivalent to this:
    for my $is (1) { # one iteration with $is=1 $target =~ s//are/; }
    I, however, am getting different results than you under 5.6:
    thare is a test of the servise
    I get the same results by dropping the loop entirely and doing just this:
    $target =~ /is/; $target =~ s//are/;
    Like you, I find that odd. Somehow Perl is doing the equivalent of s/is/are/;.
Re: s/// operator and undef question...
by ismail (Acolyte) on Dec 13, 2000 at 05:37 UTC
    I'm sorry, i threw everybody off... the first regex is missing the "/g" from the end, thus:
    my $target = 'this is a test of the servise'; for my $is ($target =~ /is/g) { $target =~ s//are/; } print $target\n"; #yields 'thare are a test of the servaree'

    sorry about that!

    Ismail

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2024-04-26 09:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found