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

Hi Gurus,

I am a newbie to PERL and need help in string extraction from a line within a file. I have a file which has start of a process that starts a JVM and the log file has an entry like:

----- Sun Mar 8 10:51:20 2015::4426::Launching the JVM with following options.

There could be multiple entries like this since the log file is appended for each start of the application. I need to extract only the timestamp from the last attempt of start from this file to a variable and export it to do another matching in another file. Can you please help with it?

In addition, I need to convert this to the format "yyyy-mm-dd hh24:mi:ss and then export it. Will ParseDate in Date::Manip be able to help in this case?

Regards,

Jay

  • Comment on Need help in extracting timestamp from the line in a file

Replies are listed 'Best First'.
Re: Need help in extracting timestamp from the line in a file
by Anonymous Monk on Mar 09, 2015 at 07:08 UTC
Re: Need help in extracting timestamp from the line in a file
by bitingduck (Deacon) on Mar 09, 2015 at 15:42 UTC

    If your dates are very consistently formatted like that, then you can probably just create a regex to extract all the parts and reformat it. It's a decent intro regex problem.

    If your dates are more complicated (e..g Third tuesday of the month) then Date::Manip is probably a good starting point. Sometimes Date::Manip doesn't have quite what you need a little pre-processing of your target data using a regex before you feed it to Date::Manip. It will probably also handle your dates as formatted, maybe with a little preprocessing.

      Thanks for the suggestion. This is the Regex that I've come up with:

      if($_=~/Launching the JVM/){ /\-+ [A-Za-z]{3} (.*?) (.*?) (.*?)\:(.*?)\:(.*?) (\d+)::(\d+)::Launchi +ng the JVM with following options/; if ( $1 eq "Jan") { $month= "01";} if ( $1 eq "Feb") { $month= "02";} ... if ( $1 eq "Dec") { $month= "12";} if ( $2 eq " 1") { $start_date= "01";} if ( $2 eq " 2") { $start_date= "02";} ... if ( $2 eq " 9") { $start_date= "09";} if ( $3 eq " 1") { $start_hour= "01";} if ( $3 eq " 2") { $start_hour= "02";} ... if ( $3 eq " 9") { $start_hour= "09";} if ( $4 eq "1") { $start_min= "01";} if ( $4 eq "2") { $start_min= "02";} ... if ( $4 eq "9") { $start_min= "09";} if ( $5 eq "1") { $start_sec= "01";} if ( $5 eq "2") { $start_sec= "02";} ... if ( $5 eq "9") { $start_sec= "09";} print "App Start time is: $6-$month-$start_date $start_hour:$start_min +:$start_sec\n";

      However, it is failing to convert if the date / hour / min / sec is a single digit / character 0-9 and prints it something like:

      $perl get_ts.pl

      --------------------------------------

      App Start time is: 2015-04- 8 1:51:20

      --------------------------------------

      Not sure what I am doing wrong. I tried replacing .*? to \d+ but still not getting the desired results.

      Can you please suggest?

        You should check whether the match succeeds at all.
        if (/\-+ [A-Za-z]{3} (.*?) (.*?) (.*?)\:(.*?)\:(.*?) (\d+)::(\d+)::Lau +nching the JVM with following options/) { ...

        Also, use hashes and sprintf to format the numbers and convert month names:

        # Declaration my $m = 1; my %MONTH = map { $_ => $m++ } qw( Jan Feb Mar Apr May ... ); # Later in the code: $month = sprintf '%02d', $MONTH{$1};
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Need help in extracting timestamp from the line in a file
by Athanasius (Archbishop) on Mar 09, 2015 at 16:11 UTC

    Hello jayu_rao, and welcome to the Monastery!

    If your log file is very large, you should consider using the module File::ReadBackwards, which is designed for this kind of task. Here is a code outline (skeleton) to get you started (you need to fill in the parts marked ...):

    use strict; use warnings; use File::ReadBackwards; my $log = ...; my $fh = File::ReadBackwards->new($log) or die "Cannot read '$log': + $!"; my $found = 0; while (my $line = $fh->readline) { if ($line =~ /.../) # Identify a JVM line and capture the time +stamp { ...; # Re-format the timestamp and export it $found = 1; last; } } warn "No log entry found\n" unless $found;

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Thanks much Athanasius. I had used read backwards :-) and needed assistance in extracting the timestamp. Can you please look at the regex that I have come up with, in my code and suggest what is it that I am doing wrong?
Re: Need help in extracting timestamp from the line in a file
by trippledubs (Deacon) on Mar 09, 2015 at 18:14 UTC
    Once you can nail down the text that has the date in it, Time::Piece can do everything else.
    #!/usr/bin/env perl use strict; use warnings; use Time::Piece; my @dates; while (<DATA>) { next unless /Launching the JVM with following options/; my ($date, $line) = split /::/,$_,2; $date = Time::Piece->strptime($date, "----- %a %b %d %T %Y"); push @dates, [ $date, $line ]; } for (@dates) { print $_->[0]->strftime("%Y-%m-%d %T") . " $_->[1]"; } __DATA__ ----- Sun Mar 8 10:51:20 2015::4426::Launching the JVM with following +options. # 2015-03-08 10:51:20 4426::Launching the JVM with following options.
    Change for to while while reading (<DATA>).. so you don't read all into memory at once
      Thanks trippledubs and every one. Time::Piece helped me with this requirement.

      Regards,

      Jay