Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Array size issue

by hmb104 (Sexton)
on Oct 15, 2012 at 17:06 UTC ( #999124=perlquestion: print w/ replies, xml ) Need Help??
hmb104 has asked for the wisdom of the Perl Monks concerning the following question:

I wrote the following code to return 2 lines from tail -f command:
open my $tailf, "tail -f $logFile |" or die; while (<$tailf>) { chomp; my $line = $_; if($line =~ m/ on $ipaddress/) { if (scalar(@matches) <= 2){ push(@matches, $line); } else { exit(0); } foreach $line (@matches){ print "$line\n"; } } }

The problem is I should be getting 2 lines but instead I get 6 lines? Any ideas what I'm doing wrong? to run it: ./script string

Comment on Array size issue
Download Code
Re: Array size issue
by Anonymous Monk on Oct 15, 2012 at 17:13 UTC
    You don't want to exit(0). You want to break out of the loop with last. Then, after the loop, not within it, you want to output your results.

    Take some lines of the source file and walk through a printout of the code, using your fingertips. Ask yourself the questions that you ask the computer to make, and do what you have told the computer to do in response to them. The flaws in your present design will quickly become clear to you as they will best with no other way.

      Which loop are you talking about? foreach? Or do you mean the if conditions?

      This is what I got from your reply, but still not working, this time I get nothing:

      while (<$tailf>) { chomp; my $line = $_; if($line =~ m/ on $ipaddress/) { if (scalar(@matches) <= 3){ push(@matches, $line); } } last; } foreach $line (@matches){ print "$line\n"; }
Re: Array size issue
by choroba (Abbot) on Oct 15, 2012 at 17:14 UTC
    You are printing all the lines each time. It means the output look like this:
    line1 line1 line2 line1 line2 line3
    These are printed as three groups (containing 1, 2 and 3 lines). The last group has 3 lines, because you push when @matches has 2 elements.
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Array size issue
by blue_cowdawg (Monsignor) on Oct 15, 2012 at 17:15 UTC
        The problem is I should be getting 2 lines but instead I get 6 lines? Any ideas what I'm doing wrong? to run it: ./script string

    There must be six lines in the logfile you are tailing. Default behavior of the tail command is to list the last 10 lines in a file. This isn't really an array size issue at all.


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

      This is a tail -f and the log file is a dhcp log so it has A LOT of lines not only 10 :)

            dhcp log so it has A LOT of lines not only 10 :)

        Here's a live example for you:

        $ tail -f multtable.txt 0 9 18 27 36 45 54 63 72 81
        The code that generated that was:
        for ix in 0 1 2 3 4 5 6 7 8 9 do for iy in 0 1 2 3 4 5 6 7 8 9 do n=`expr ${ix} '*' ${iy}` echo $n >> multtable.txt done done
        That makes 100 lines. I do a "tail -f" and I see the last 10 lines all day long until someone writes to it. While I can't comment on the data set you are working with I can tell you about the behavior of most *nix commands.


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Array size issue
by blue_cowdawg (Monsignor) on Oct 15, 2012 at 17:55 UTC

    if($line =~ m/ on $ipaddress/) { if (scalar(@matches) <= 2){ push(@matches, $line); } else { exit(0); } foreach $line (@matches){ print "$line\n"; } }
    This is where your trouble is. You probably meant to write it thusly:
    if($line =~ m/ on $ipaddress/) { if (scalar(@matches) <= 2){ push(@matches, $line); } else { foreach $line (@matches){ print "$line\n"; } exit(0); } }


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

      That is not what I want. I want to save the line to the array if it matches the expression. I don't want to print anything this is just for debugging to make sure my array is containing the proper lines.

            That is not what I want.

        Sorry.... could have fooled me considering the logic in your original post.

        If I break your code down into pseudo-code it reads like this:

          open a pipe to the tail -f command for a logfile (unnamed)
          iterate over the pipe
            if less than 3 files are in array
              if the line matches a (undetermined) IP address
                push the line into an array
              otherwise
                exit the program
            Iterate over the contents of the array
              print line

        Part of the art of getting good answers on Perl Monks is being concise about your questions and not leaving what you are after up to the interpretation of the reader.

        Once again I will attempt to extrapolate what you are after. You code will work better if you don't put the print lines in and change the exit for last.


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Array size issue
by betterworld (Deacon) on Oct 15, 2012 at 20:17 UTC

    You can do this a lot easier and shorter:

    open my $tailf, "tail -f $logFile |" or die; for (1,2) { my $line = ''; $line = <$tailf> until $line =~ / on $ipaddress/; push @matches, $line; }
    (Okay, you'd have to include some check for eof so it won't get into an endless loop if the input is too short. But I won't change it because it's so nice and short :)
Re: Array size issue
by smile4me (Sexton) on Oct 15, 2012 at 22:25 UTC

    Is there a reason you are using "tail -f" in your file handle, as opposed to "tail -n 10" or similar. In my system, the script hangs waiting for additional input to the file. Here's an alternative idea for you to consider:

    my @list; my $file = q[/path/to/some/file]; my $regex = qr[your pattern]; open my $fh, "tail $file |" or die; while (<$fh>) { chomp; say "testing: $_"; push @list, $_ if ( $_ =~ $regex); last if (@list >= 2); } local $"="\n"; say "found: @list";

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (12)
As of 2014-10-01 15:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    What is your favourite meta-syntactic variable name?














    Results (29 votes), past polls