in reply to Looping on a match, and value of $1

The first loop executed $a =~ /(\d+)/g once producing a list of "1", "2", and "5". The last iteration of the expression left $1 set to "5" so when $_ was "1", you added "5". When $_ was "2" you added "5". When $_ was "5", you added "5".

Try the first one replacing for() with while() and you'll see what you expected. Look in perlre at the 'g' flag in list versus scalar context. Also look at perlsyn for the difference between foreach and while.

Replies are listed 'Best First'.
Re^2: Looping on a match, and value of $1
by pg (Canon) on Jul 24, 2004 at 03:17 UTC

    Think it is just a typo or the expression was not precise, this left me wondering: The last iteration of the expression left $1 set to "5"

    His original code has two seperate perl -e, so this does not really fit, as the two for loops are not related at all. Even if there is only one perl -e, $1 still will be reset when the second // is executed.

    But I believe diotalevi made the point (precisely in his mind). The whole point is that, the // is not executed for each iteration, but once at the begin. The for loop does not loop through the //, but rather the array produced by //. $_ always takes the current value of the current element when it loops, but $1 has nothing to do with the loop, and its value stays.

    Thought just add a bit code to back up what he said (there will never be any harm to do a little bit experiment):

    use strict; use warnings; my $t; #comment out one of the next two lines #$a="1b2cde5";for($a=~/(\d+)/g){display($_, $1); $t+=$1;};print "$t\n" +; $a="1b2cde5";for($a=~/(\d+)/g){display($_, $1); $t+=$_;};print "$t\n"; sub display { print "_ = " . shift() . ", 1 = " . shift() . "\n"; }

    Comment out the first one, you get:

    _ = 1, 1 = 5 _ = 2, 1 = 5 _ = 5, 1 = 5 8

    Comment out the second one, you get:

    _ = 1, 1 = 5 _ = 2, 1 = 5 _ = 5, 1 = 5 15