How to search lines in a file between two timestamps using Perl?

In Perl, I'm trying to read a log file and print only lines with a timestamp between two specific times. The time format is hh: mm: ss, and this is always the third value for each log. For example, I would look for lines that will fall between 12:52:33 to 12:59:33

I am new to Perl and have no idea what route to take to even start programming this. I am pretty sure that this will use some type of regular expression, but for the life of me I can’t even understand what it will be. Can someone please help me with this.

Also, to make it more complex, I have to do it with the basic Perl modules, because my company will not allow me to use any other modules until they are tested and verified that there will be no The negative consequences for any of the systems script may interact.

+5
source share
4 answers

In pseudo code, you would do something like this:

  • read the file line by line:
    • parse timestamp for this line.
    • If it is less than the start time, go to the next line.
    • if it is longer than the end time, go to the next line!
    • else: this is the line you want: print.

, -- .. , .

stdin :

while (my $line = <>)
{
     # do stuff...
}

split (. perldoc -f split). , .

( ), . perldoc perlre.

-, :

use strict;
use warnings;

use POSIX 'mktime';
my $starttime = mktime(33, 52, 12);
my $endtime = mktime(33, 59, 12);

while (my $line = <>)
{
    # split into fields using whitespace as the delimiter
    my @fields = split(/\s+/, $line);

    # the timestamp is the 3rd field
    my $timestamp = $fields[2];

    my ($hour, $min, $sec) = split(':', $timestamp);
    my $time = mktime($sec, $min, $hour);

    next unless ($time < $starttime) .. ($time > $endtime);
    print $line;
}
+2

, Perl -:

perl -ne 'print if /12:52:33/../12:59:33/' logFile

, "" script:

use strict;
use warnings;

open my $log, '<', 'logFile';

my $startTime = get_start_time();  # Sets $startTime in hh:mm:ss format
my $endTime = get_end_time();      # Sets $endTime in hh:mm:ss format

while ( <$log> ) {

    print if /$startTime/../$endTime/;
}

Ether, , . , :

use strict;
use warnings;
use autosplit;

open my $log, '<', 'logFile';

my $startTime = get_start_time();  # Sets $startTime in hh:mm:ss format
my $endTime = get_end_time();      # Sets $endTime in hh:mm:ss format

while ( <$log> ) {

    my $time = (split /,/, $_)[2];      # Assuming fields are comma-separated
                                        # and timelog is 3rd field

    last  if $time gt $endTime;         # Stop when stop time reached
    print if $time ge $startTime;
}
+2

, 'sed' :

sed -n '/12:52:33/,/12:59:33/p' logfile

.

Perl, s2p, sed Perl.

Perl :

my $atfirst = 0;
my $atend = 0;
while (<>)
{
    last if $atend;
    $atfirst = 1 if m/12:52:33/;
    $atend = 1 if m/12:59:33/;
    if ($atfirst)
    {
        process line as required
    }
}

, , , . , "" .

+1
source

If your log files are divided by day, you can convert the timestamps in seconds and compare them. (If not, use the technique as my answer to the question you asked earlier .)

Say your magazine

12:52:32 outside
12:52:43 strictly inside
12:59:33 end
12:59:34 outside

Then with

#! /usr/bin/perl

use warnings;
use strict;

my $LOGPATH = "/tmp/foo.log";

sub usage { "Usage: $0 start-time end-time\n" }

sub to_seconds {
  my($h,$m,$s) = split /:/, $_[0];
  $h * 60 * 60 +
       $m * 60 +
            $s;
}

die usage unless @ARGV == 2;
my($start,$end) = map to_seconds($_), @ARGV;

open my $log, "<", $LOGPATH or die "$0: open $LOGPATH: $!";
while (<$log>) {
  if (/^(\d+:\d+:\d+)\s+/) {
    my $time = to_seconds $1;
    print if $time >= $start && $time <= $end;
  }
  else {
    warn "$0: $LOGPATH:$.: no timestamp!\n";
  }
}

You will get the following result:

$ ./between 12:52:33 12:59:33
12:52:43 strictly inside
12:59:33 end
0
source

All Articles