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

I have a Perl program that does not seem to be calculating numbers right. It parses a log file with lines in this format:
#ErrorLevel,Computer,IDO,Description,MinValue,MinTime,MaxValue,MaxTim +e,CurrentValue,CurrentTime 0,localhost,1.3.6.1.4.1.314.50.1.20.3.1.3,CFG persistent MEM,18720,11: +29,18760,12:30,17176,14:26
The code is supposed to see how the current values (from the %CONFIG hash) compare to the min and max values from the log, then make it the min_value or max_value if it is less than or greater than them (respectively). Here's a snippet of the code:
if (! /^\s*(\d),(\w+),([\d\.]+),([^,]+),([^,]+),(\d+:\d+),([^,]+),(\d+ +:\d+),.*$/ ) { exit_error("Cannot parce log file") } $level=$1; $computer=$2; $iod=$3; $comment=$4; $min_value=$5; $min_time=$6; $max_value=$7; $max_time=$8; if ( $CONFIG{$computer}{iod}{$iod}{value} =~ /\w+/ ) {} elsif ( $CONFIG{$computer}{iod}{$iod}{value} < $min_value ) { $min_value = $CONFIG{$computer}{iod}{$iod}{value}; $min_time = "$hour:$min"; } elsif ( $CONFIG{$computer}{iod}{$iod}{value} > $max_value ) { $max_value = $CONFIG{$computer}{iod}{$iod}{value}; $max_time = "$hour:$min"; } print LOG "$level,$computer,$iod,$comment,$min_value,$min_time,$max_va +lue, $max_time,$CONFIG{$computer}{iod}{$iod}{value},$hour:$min\n";
The problem is that at least sometimes have a current value that is less than the min_value, but doesn't get passed on to it (as in the log file line above).

Replies are listed 'Best First'.
(Ovid) Re: When is not necessarily
by Ovid (Cardinal) on Oct 04, 2001 at 02:11 UTC

    Not sure what your problem is, offhand, but I cleaned up your code a little bit and through in some sanity checking that might help:

    my ( $level, $computer, $iod, $comment, $min_value, $min_time, $max_va +lue, $max_time ) = split ',',$_; if ( exists $CONFIG{ $computer } and exists $CONFIG{ $computer }{ iod } and exists $CONFIG{ $computer }{ iod }{ $iod } and exists $CONFIG{ $computer }{ iod }{ $iod }{ value } ) { my $value = $CONFIG{$computer}{iod}{$iod}{value}; if ( $value !~ /\D/ ) { if ( $value < $min_value ) { $min_value = $value; $min_time = "$hour:$min"; } elsif ( $value > $max_value ) { $max_value = $value; $max_time = "$hour:$min"; } print LOG "$level,$computer,$iod,$comment,$min_value,$min_time +,$max_value,$max_time,$value,$hour:$min\n"; } else { warn "Computer: $computer iod: $iod had the following value in + the log: $value"; } } else { # have some appropriate warnings for the missing hash element }

    Cheers,
    Ovid

    Vote for paco!

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: When is not necessarily
by tommyw (Hermit) on Oct 04, 2001 at 02:19 UTC

    If the initial value in your config hash contains any word character (alpha, numeric, or underscore), then the first branch will be taken, and nothing will happen.

    And, of course, the obligatory cleaned up code:

    ($level, $computer, $iod, $comment, $min_value, $min_time, $max_value, + $max_time)= /^\s*(\d),(\w+),([\d\.]+),([^,]+),([^,]+),(\d+:\d+),([^,]+),(\d+:\d+) +,.*$/ or exit_error("Cannot parse log file"); $clip=CONFIG{$computer}{iod}{$iod}{value}; if ($min_value<$clip) { $min_value=$clip; $min_time="$hour:$min"; } elsif ($max_value>$clip) { $max_value=$clip; $max_time="$hour:$min"; } print LOG (join ',', $level, $computer, $iod, $comment,$ min_value, $m +in_time, $max_value, $max_time, $clip, "$hour:$min"), "\n";

    (Or you could possibly use split on the input line...)

    Update: Whoops! I thought that logic was odd: I've inadvertantly reversed the sense of the tests. Its hould be $clip<$min_value and $clip>$max_value of course.

      Is there a way to force it to be a number?

      melguin

        In perl you don't need to force anything to be a number. Use it like a number and it will behave like a number, use it like a string and it will behave like a string.

        print "1 + " . 1 . " = " , eval ( "1 + " . 1 );

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print