http://qs1969.pair.com?node_id=357410

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

I've been working with this off and on for some time. I have a couple solutions that work however I don't feel they are as clean as they can be. I'm trying to use a loop and have run into some trouble. I "thought" I was asking perl to print any lines that match my @matches list. It comes back blank. I've been searching several books and google. I'm just not seeing the mistake. What am I missing?

Here is the code. Any insights on what I missed is greatly appreciated.

use strict; use warnings; my @netstat = `netstat -s`; my @matches=("invalid headers", "packets dropped"); foreach my $matches (@netstat) { my @results = grep(/@matches/, @netstat); #print "I am here\n"; print @results; }

Replies are listed 'Best First'.
Re: Trouble with foreach loop.... I think
by arturo (Vicar) on May 29, 2004 at 03:53 UTC
    In a way, your code is doing exactly what you say you want it to: it is indeed matching every line in @netstat that matches [your] @matches list", but the way perl interprets that probably doesn't capture what you're thinking, What your code does is give you every line in the netstat output that matches *your entire @matches array*, interpreting that array as a string. The matching operator is a double-quote context (just like print "@matches"). And, as it says in perldata:
    Arrays and slices are interpolated into double-quoted strings by joining the elements with the delimiter specified in the $" variable($LIST_SEPARATOR if "use English;" is specified), space by default.
    In other words, the line:
    my @results = grep( /@matches/, @netstat );
    comes out (given the rest of your code) as equivalent to my @results = grep(/invalid headers packets dropped/, @netstat); in other words it's trying to find that whole "phrase."

    I think you also mixed up your foreach loop, which loops over @netstat, when I think what you wanted was to check each element in @matches; putting all that together, I think your loop should be:

    foreach my $match (@matches) { my @results = grep /$match/, @results; print @results; }

    HTH

    If not P, what? Q maybe?
    "Sidney Morgenbesser"

      I see the confusion in my code now. I modified it and all is well. I must have read through that section in "Learning Perl 3rd Edition" a dozen times and still didn't get it :-)

      Thanks for the help!
Re: Trouble with foreach loop.... I think
by mifflin (Curate) on May 29, 2004 at 03:56 UTC
    It looks like you may be trying to print out any lines returned from your netstat command that have the strings "invalid headers" or "packets dropped" in them. If so, I think this may be something that will work for you...
    my @netstat = `netstat -s`; my @matches=("invalid headers", "packets dropped"); my $matches = join('|', @matches); foreach (@netstat) { print if /$matches/; }
    However, if you go through alot of records this will be slow as it has to reparse the regular expression over and over. If your regex (list of strings to match) is truely variable and you process lots of records then it might be more efficient to assemble some perl code and eval it. The advanced perl book ( the one with the panther on it ) has a good example in it in the eval chapter.