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

Hi Monks!,

I have a log file that I am wanting to search for the current date and if you finds the current date in the file with a error, capture the line with date and time. The problem I have is that it will print several or hundreds of lines because the file will contain many lines with the date and time. That said, I just want to send a message with the ONE line when it encounters an API error on that particular date.
Example: Log File Line Containing Date [1/21/2008 4:33 AM] API call error
print "\n"; print "======================================\n"; $aDate = &get_cur_time; print "=====================================\n"; open(FH, "c:\sync.log") || die "Cannot open Log:$!\n"; while (<FH>) { if ($aDate) { print "ERROR\n"; } }; close(FILE); print "\n"; ### Getting a time format for printing ### sub get_cur_time { my $Second; my $Minute; my $Hour; my $Day; my $Month; my $Year; my $WeekDay; my $DayOfYear; my $IsDST; ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); my $RealMonth = $Month + 1; $RealMonth = "0" . $RealMonth if($RealMonth < 10); $Day = "0" . $Day if($Day < 10); $Hour = "0" . $Hour if($Hour < 10); $Minute = "0" . $Minute if($Minute < 10); $Second = "0" . $Second if($Second < 10); my $Fixed_Year = $Year + 1900; ### Making Date Format For Files ### #return "$RealMonth$Day$Fixed_Year"; ### Different Format ### print "Today's Date is: $RealMonth/$Day/$Fixed_Year $Hour:$Minute:$Sec +ond\n"; };

Replies are listed 'Best First'.
Re: Reading log file for current date
by hipowls (Curate) on Jan 25, 2008 at 21:57 UTC

    You should use warnings and strict. It will pick up typos such as close FILE when you meant close FH

    The whole date generation can be done more simply with sprintf

    sub get_cur_time { # Use a slice to get just the bits I need my ( $Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay ) = (localtime)[ 0 .. 5 ]; return sprintf '%0.2d/%0.2d/%0.4d %0.2d:%0.2d:%0.2d', $Month + 1, +$Day, $Year + 1900, $Hour, $Minute, $Second; }

    You also need to test if the line matches $aDate

    while( my $line = <FH> ) { if ( $line =~ /\Q$aDate\E/ ) { print $line; } }
    I put $aDate between \Q and \E so that any character that has a special meaning in the regex is escaped.

Re: Reading log file for current date
by toolic (Bishop) on Jan 25, 2008 at 22:09 UTC
    Is this what you are looking for?
    #!/usr/bin/env perl use warnings; use strict; my $today = get_cur_time(); while (<DATA>) { if (/API call error/) { my ($date, $time, $suffix) = split; $date =~ s/\[//; $suffix =~ s/]//; if ($date eq $today) { print "Error occurred: date=$date, time=$time $suffix\n"; } } } exit; sub get_cur_time { my ($Day, $Month, $Year) = (localtime(time))[3..6]; $Year += 1900; $Month = sprintf '%02d', $Month + 1; $Day = sprintf '%02d', $Day; return "$Month/$Day/$Year"; } # Example: Log File Line Containing Date __DATA__ [01/25/2008 4:33 AM] foo [01/25/2008 5:33 AM] bar [01/25/2008 10:01 AM] API call error [01/25/2008 11:55 PM] baz [01/26/2008 10:01 AM] API call error

    This prints out:

    Error occurred: date=01/25/2008, time=10:01 AM
Re: Reading log file for current date
by toolic (Bishop) on Jan 25, 2008 at 21:53 UTC
    I refactored your get_cur_time function, and renamed it as print_cur_time:
    #!/usr/bin/env perl use warnings; use strict; print_cur_time(); exit; sub print_cur_time { my ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; $Month = sprintf '%02d', $Month + 1; $Day = sprintf '%02d', $Day; $Hour = sprintf '%02d', $Hour; $Minute = sprintf '%02d', $Minute; $Second = sprintf '%02d', $Second; print "Today's Date is: $Month/$Day/$Year $Hour:$Minute:$Second\n" +; }

    I just wanted to point out that you can use sprintf to pad a zero to single-digit numbers. I hope this is of use to you.

      Yes, that was very helpful and reduced the code. Thank you!
Re: Reading log file for current date
by pc88mxer (Vicar) on Jan 26, 2008 at 06:01 UTC
    If your log file is large, considering using a binary search technique to locate the desired line. I'm sure there's a CPAN module to do this, but I can't seem to find it at the moment. I did find this perlmonks writeup which basically describes what to do: http://www.perlmonks.org/?node_id=260659

    Another heuristic to use would be to begin the search near the end of the file (since it is a log file and today's entries will occupy the tail end of it -- unless, of course, your applications are running in the future.)