Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Simple log parser

by Anonymous Monk
on Aug 15, 2002 at 14:04 UTC ( #190401=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I have a log of working hours which I'd like to parse. The idea is that I calculate the net hours I've done from this file and insert these values into a MySQL db. The log file has the following format (one entry per line):

dd-mm-yy hh:mm am-dd-mm-yy hh:mm pm

I've been using the regex below to pull out all the values (which works fine) and work out the hours. The one small hitch is that I need to convert pm hours into 24h format for the calculation to work (i.e. 3pm should become 15h). I've tried to do this with a conditional but cannot get it to evaluate properly - all times, regardless if am or pm, get converted to 24h format.
@lines = <LOGFILE>; foreach $line (@lines) { if ($line != m/\s/) { # regex to turn dates into epoch ($dd, $mm, $yy, $hh, $mt, $tt, $tdd, $tmm, $tyy, $thh, $tmt, $ttt) = $ +line =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+)\s(am|pm)-(\d+)-(\d+)-(\d+)\s( +\d+):(\d+)\s(am|pm)/; if ($tt == 'pm') { $hh = $hh + 12; } if ($ttt == 'pm') { $thh = $thh + 12; } $t_from = timelocal(0,$mt,$hh,$dd,$mm,$yy); $t_to = timelocal(0,$tmt,$thh,$tdd,$tmm,$tyy); $s_elapsed = $t_to - $t_from; ...
I'm guessing that this is one of those extremely simple problems - I just can't see where I'm going wrong. Any help would be greatly appreciated!


Replies are listed 'Best First'.
Re: Simple log parser
by seeker (Curate) on Aug 15, 2002 at 14:16 UTC
    Shouldn't your string compares (i.e. ($tt == 'pm')) use the eq operator ($tt eq 'pm')? Try it with that change.
Re: Simple log parser
by dimmesdale (Friar) on Aug 15, 2002 at 14:20 UTC
    @lines = <LOGFILE>; foreach $line (@lines) { if ($line != m/\s/) { # regex to turn dates into epoch ($dd, $mm, $yy, $hh, $mt, $tt, $tdd, $tmm, $tyy, $thh, $tmt, $ttt) = $ +line =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+)\s(am|pm)-(\d+)-(\d+)-(\d+)\s( +\d+):(\d+)\s(am|pm)/;
    You say dd-mm... but then in the regex you have \d+. If you want to have just two digits, then something like this would work:
    $line =~ /(\d\d)-(\d\d)\s+(\d\d):(\d\d)\s+([ap]m)-(\d\d)-(\d\d)-(\d\d) +\s+(\d\d):(\d\d)\s+[ap]m/

    Notice I changes (am|pm) to [ap]m. Character class is faster than alternation, and since m is repeating in both you don't need to have that included in the alternative. Have you looked at the various Date:: modules?

    if ($tt == 'pm') { $hh = $hh + 12; } if ($ttt == 'pm') { $thh = $thh + 12; }

    Uh-ohh.... someone didn't have use strict/use warnings on ... did they?

    if ($tt eq 'pm') { $hh += 12; } if ($ttt eq 'pm') { $thh += 12; }

    You'll notice I used the perlop 'eq' here (== is numeric, we don't want numeric; use strict/use warnings issues a warning for this I believe). I also changed the $a = $a + $b form to $a += $b. Not necessary, but it looks a little better (to me :).

Re: Simple log parser
by grummerX (Pilgrim) on Aug 15, 2002 at 14:13 UTC
    Take a look at the Delta_DHMS function in Date::Calc.

    -- grummerX

Re: Simple log parser
by Anonymous Monk on Aug 15, 2002 at 15:21 UTC
    Wow! Thank you all kindly for your quick responses. The script works now. BTW, I didn't look into any of the Date:: modules because I wanted to try and stay with the standard Perl stuff. Anyway, thanks again!

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://190401]
Approved by Courage
and the monks are chillaxin'...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2017-02-19 15:56 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (292 votes). Check out past polls.