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

Hey friends,
I've got a simple problem that is just driving me up the wall, I can't really figure out why this isn't working so I'll ask for your wisdom:
use strict; my($web,$incident_id); $web = " bla log_id=12345& bla Label Defect bla> bla log_id=53456& bla Label Defect bla> bla log_id=13642& bla Label Defect bla> bla log_id=48735& bla Label Defect bla> "; print "$web\n"; foreach ($web =~ m/(log_id\=(\d*)\&.*?Label Defect)/gm) { print "Found \"Label Defect\"\n"; $incident_id = $2; print "INC: $incident_id\n"; print "$1\n"; do "stuff for each $incident_id"; }

It keeps repeating the same $incident_id, can I get the loop to progress?

Replies are listed 'Best First'.
Re: foreach (shenanigans)
by Abigail-II (Bishop) on Jan 14, 2003 at 23:38 UTC
    That's because you have a foreach. That puts the match in LIST context; the match happens once, returning all the captured matches. That's why you get 8 times the same result. Change the foreach to while, and you get what you want.

    Abigail

      I considered a "while", I was just wondering why it (foreach) only evaluated one time... Thanks.
        I am going to guess with the while you neglected to add the g modifier to the regular expression, and thus it would have evaluated only once.

        update:misread the question. my err.

        -enlil

Re: foreach (shenanigans)
by gjb (Vicar) on Jan 14, 2003 at 23:40 UTC

    Replace the foreach with a while and your problem is solved.

    The point is that in the foreach the regular expression gets evaluated in list context, and that the match which sets the $1 and $2 is the last one. After that the loop is done a number of times, but each time with exactly the same $1 and $2.

    With a while on the other hand, the regex is evaluated each time through the loop and sets the $1 and $2 to the appropriate values.

    Hope this helps, -gjb-

Re: foreach (shenanigans)
by Zaxo (Archbishop) on Jan 15, 2003 at 00:37 UTC

    The reason your version fails the way it does is that all the matches are done at once in constructing the foreach list. When you finally start looping, $1 and $2 are leftovers from the last matching line in $web.

    You can set up with foreach like this:

    foreach (split "\n", $web) { if (m/(log_id\=(\d*)\&.*?Label Defect)/m) { #... etc } }
    or with 5.8.0 you can get a little crazed with
    { open my $foo, '<', \$web or die $!; while (<$foo>) { if (m/(log_id\=(\d*)\&.*?Label Defect)/m) { #... etc } } }
    It would also be good to limit the scope of my $incident_id to within the if block, where it is assigned and used.

    After Compline,
    Zaxo