0

I'm trying to parse out data from a log file spanning over multiple lines (shown below).

Archiver Started: Fri May 16 00:35:00 2014
Daily Archive for (Thu) May. 15, 2014 STATUS: Successful Fri May 16 00:37:43 2014
Daily Archive for (Thu) May. 15, 2014 STATUS: Successful Fri May 16 00:39:54 2014
Archiver Completed: Fri May 16 00:42:37 2014

I want to split on Archiver Started: on the first line and split on Archiver Completed: on the last line for anything in between these lines. So I would be left with the following:

Daily Archive for (Thu) May. 15, 2014 STATUS: Successful Fri May 16 00:37:43 2014
Daily Archive for (Thu) May. 15, 2014 STATUS: Successful Fri May 16 00:39:54 2014

As sometimes the there can be a single or multiple entry for one day, week or month.

Is this possible with a Regex?

Miller
  • 34,962
  • 4
  • 39
  • 60
Ko_Na_H
  • 33
  • 4
  • You can use regex modifier `s` to treat the whole text as a single line: http://perldoc.perl.org/perlre.html#Modifiers – VladimirM Aug 12 '14 at 22:02
  • Also see [How can I pull out lines between two patterns that are themselves on different lines?](https://metacpan.org/pod/perlfaq6#How-can-I-pull-out-lines-between-two-patterns-that-are-themselves-on-different-lines) from `perlfaq6`. – ThisSuitIsBlackNot Aug 12 '14 at 22:21

2 Answers2

3

Use a Range Operator ...

The return value of a flipflop is a sequence number (starting with 1), so you simply need to filter out 1 and the ending number which has the the string "E0" appended to it.

use strict;
use warnings;

while (<DATA>) {
    if (my $range = /Archiver Started/ .. /Archiver Completed/ ) {
        print if $range != 1 && $range !~ /E/;
    }
}

__DATA__
stuff
more stuff
Archiver Started: Fri May 16 00:35:00 2014
Daily Archive for (Thu) May. 15, 2014 STATUS: Successful Fri May 16 00:37:43 2014
Daily Archive for (Thu) May. 15, 2014 STATUS: Successful Fri May 16 00:39:54 2014
Archiver Completed: Fri May 16 00:42:37 2014
other stuff
ending stuff

Outputs:

Daily Archive for (Thu) May. 15, 2014 STATUS: Successful Fri May 16 00:37:43 2014
Daily Archive for (Thu) May. 15, 2014 STATUS: Successful Fri May 16 00:39:54 2014
Miller
  • 34,962
  • 4
  • 39
  • 60
1

you can use next trick:

my @result = ();
my $catch;
LINE:
for my $line ( @lines ) {
    if ( $line =~ m/^Archiver Started/i ) {
        $catch = 1;
        next LINE;
    } elsif ( $line =~ m/^Archiver Completed/i ) {
        $catch = 0;
        next LINE;
    }
    next LINE unless $catch;
    push @result, $line;
}
krevedko
  • 4,187
  • 1
  • 17
  • 13