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

My question is similar to this one, but I'm pretty much a newbie so I have a question in addition: I understand how to throw a file line-by-line into an array, but how could I search the array for "Down" in one element and "Up" in a following (not necessarily the next) element? I'm trying to generate stats from a router log that looks something like this:
a_time_down Down a_time_up Up a_time_down Down a_time_down Down a_time_up Up
I have to come up with a aggregate downtime from a log like this. I found Time::ParseDate (what a blessing!), so once I know which Down element cooresponds with the next Up, tallying up the downtime shouldn't be a problem. Thanks so much for your help; I'm pretty new to Perl so please be kind. :)

Replies are listed 'Best First'.
Re: How do I parse and evaluate a file line-by-line?
by Trimbach (Curate) on Mar 03, 2001 at 08:39 UTC
    Here's one quick solution:
    #!/usr/bin/perl -w use strict; my $last = ""; my $cursor = -1; my @output; while (<DATA>) { my ($time, $switch) = split "\t"; if ($switch eq $last) { $output[$cursor] = $_; } else { $cursor++; $output[$cursor] = $_; $last = $switch; } } foreach (@output) { print; } __DATA__ time1 UP time2 DOWN time3 UP time4 DOWN time5 DOWN time6 DOWN time7 UP time8 UP time9 UP time10 DOWN time11 UP
    The idea here is to record just the last "UP" or "DOWN" event in a string of one or more "UP" or "DOWN" events. $cursor is used to keep our place in the array, overwritting successive UP's and DOWN's as necessary.

    Gary Blackburn
    Trained Killer

      You can tighten that middle loop up a bit by getting out of "C think" and getting into "Perl think":
      while (<DATA>) { my ($time, $switch) = split "\t"; if ($switch eq $last) { $output[-1] = $_; } else { push @output, $_; $last = $switch; } }
      The $cursor variable is unnecessary, because Perl always knows how long the array is.

      -- Randal L. Schwartz, Perl hacker

        Thanks for that... I rarely use $array[$element] to grow an array, preferring "push", but I couldn't use push indiscriminately here because I needed to write over successive instances of UP or DOWN. Of course, $array[-1] was exactly what I was looking for. Gotta get used to using the relative position in an array....

        And for the record, it wasn't "C think" as I actually know absolutely nothing about C. It was just inexperience. :-D

        Gary Blackburn
        Trained Killer

Re: How do I parse and evaluate a file line-by-line?
by Tuna (Friar) on Mar 03, 2001 at 08:55 UTC
    one way is like this:
    #!/usr/bin/perl -w use strict; my $file = "/home/trix/lines"; my $line; my @array; open (FILE, "$file") || die "Can't open $file: $!\n"; while ($line = <FILE>) { chomp $line; next unless ($line =~ /Down/); my ($downtime, $down) = split(' ', $line); push (@array, $downtime); } my $agg = eval join '+', @array; #the above beauty came from somewhere here; don't remember where print "My downtime is $agg\n";
    ....if I am understanding correctly that the first element in each log file is actually a number, and there is only one other element, the interesting one being "Down".