On Jun 28, Ryan Frantz said:

I'm working on a script that iterates over a log file looking for known
hosts so that their messages can be grouped in a summary report.
However, when I run the script, the array I create includes entries for
previous hosts that were found.  I thought that I could empty the array
at the beginning of the loop but this did not work.  Any ideas would be
appreciated; see code below:

The @lines array is only half your issue -- you also need to clear the %line_count hash.

But this could be made a whole lot simpler by PROPERLY scoping your variables. Don't declare all of them at the top of your program, declare them in the scope in which they should exist.

  #!/usr/bin/perl

  use strict;
  use warnings;

  my @logfile = <>;
  my @hosts = qw( ... );
  my @keywords = qw( ... );

Ok, that's good so far.  Now, when you do:

  for my $x (@y) {
    $x =~ s/this/that/;
  }

you're *actually* modifying the elements in @y, because $x isn't a *copy* of each element, it's an *alias* to each element. Therefore, instead of looping over @logfile and doing substitutions each time, let's fix up the contents of the array right now before we go on:

  for (@logfile) {
    s/\d+/#/g;
    s/^.*: //;
    chomp;
  }

Ok, now we can continue:

  for my $host (@hosts) {
    my @lines;

    for (@logfile) {
      push @lines, $_ if /$host/i;
    }

Let's rewrite that.  That could be done as a grep() statement:

    my @lines = grep /$host/i, @logfile;

Now we work with %line_count.

    my %line_count;

    for (@lines) {
      $line_count{$_}++;
    }

You don't need to do the special-case stuff you had. If a hash key doesn't exist yet, and you use it like it DOES exist, Perl adds it for you, no questions asked.

Then you go through this hash and print it:

    for (sort keys %line_count) {
      print "$_: $line_count{$_}\n";
    }
  }

But we can go one step further: @lines is only used twice -- we put stuff into it, and then we read from it. We can get rid of the array and just use the return value from grep() in-place:

  for my $host (@hosts) {
    my %freq;

    $freq{$_}++ for grep /$host/i, @logfile;

    # open file
    for (sort keys %freq) {
      print "$_: $freq{$_}\n";
    }
    # close file
  }

Voila.

--
Jeff "japhy" Pinyan         %  How can we ever be the sold short or
RPI Acacia Brother #734     %  the cheated, we who for every service
http://japhy.perlmonk.org/  %  have long ago been overpaid?
http://www.perlmonks.org/   %    -- Meister Eckhart

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to