capser
capser

Reputation: 2635

Perl : How to print lines in between two of the same patterns?

I have some data called data_range.txt. Ultimately I want to load the data into an array and compare the strings. However I cannot print the lines between the two -- patterns.

--
2020-10-07T22:14:27,545 DEBUG [recvMsgProc-0] <KdbQMHandler> calling:parameters=191216CV0
2020-10-07T22:14:27,554 INFO  [recvMsgProc-0] <KdbQMHandler> resultkx.Flip@
--
2020-10-07T22:43:12,345 DEBUG [recvMsgProc-1] <KdbQMHandler> calling:parameters=00774MAB1
2020-10-07T22:43:12,354 INFO  [recvMsgProc-1] <KdbQMHandler> resultkx.Flip@
--
2020-10-07T22:44:02,028 DEBUG [recvMsgProc-0] <KdbQMHandler> calling:parameters=00774MAB1
2020-10-07T22:44:02,036 INFO  [recvMsgProc-0] <KdbQMHandler> resultkx.Flip@
--
2020-10-07T22:55:10,691 DEBUG [recvMsgProc-1] <KdbQMHandler> calling:parameters=71647NBE8
2020-10-07T22:55:10,703 INFO  [recvMsgProc-1] <KdbQMHandler> resultkx.Flip@
--

I have the script which usually works when I try and print between two different patterns, however these patterns are the same.

#!/usr/bin/perl
use warnings;
use strict;

my $file = 'data_range.txt';
open my $fh, $file  or die "Can't open $file: $!";

# Build the start and end patterns
my $beg = qr/--/;
my $end = qr/--/;

while (<$fh>)
{
    if (/$beg/ .. /$end/) {
        print if not /$end/;
    }
}

Upvotes: 1

Views: 213

Answers (2)

choroba
choroba

Reputation: 241848

You need to modify slightly the condition not to skip every second part

if (/--/ .. /--/ && next) {
    print;
}

But it might be much cleaner to abandon the range operator and use the input record separator instead:

local $/ = "--\n";
while (<>) {
    # Here $_ contains all the lines of a section
    my @lines = split /\n/;
    # ...
}

Upvotes: 3

Timur Shtatland
Timur Shtatland

Reputation: 12347

Preprocess the input using grep to remove the -- lines, and paste to change the input into a file with 2 records per line, join on tab by default. The result can be easily parsed by splitting on a tab into the records into an array of 2 record for each line.

grep -v '^--' data_range.txt | paste - - | perl -F'\t' -lane 'print join "\t", map { qq{"$_"} } @F;'

# Prints:

"2020-10-07T22:14:27,545 DEBUG [recvMsgProc-0] <KdbQMHandler> calling:parameters=191216CV0"     "2020-10-07T22:14:27,554 INFO  [recvMsgProc-0] <KdbQMHandler> resultkx.Flip@"
"2020-10-07T22:43:12,345 DEBUG [recvMsgProc-1] <KdbQMHandler> calling:parameters=00774MAB1"     "2020-10-07T22:43:12,354 INFO  [recvMsgProc-1] <KdbQMHandler> resultkx.Flip@"
"2020-10-07T22:44:02,028 DEBUG [recvMsgProc-0] <KdbQMHandler> calling:parameters=00774MAB1"     "2020-10-07T22:44:02,036 INFO  [recvMsgProc-0] <KdbQMHandler> resultkx.Flip@"
"2020-10-07T22:55:10,691 DEBUG [recvMsgProc-1] <KdbQMHandler> calling:parameters=71647NBE8"     "2020-10-07T22:55:10,703 INFO  [recvMsgProc-1] <KdbQMHandler> resultkx.Flip@"

The Perl one-liner uses these command line flags:
-e : Tells Perl to look for code in-line, instead of in a file.
-n : Loop over the input one line at a time, assigning it to $_ by default.
-l : Strip the input line separator ("\n" on *NIX by default) before executing the code in-line, and append it when printing.
-a : Split $_ into array @F on whitespace or on the regex specified in -F option.
-F'/\t/' : Split into @F on TAB, rather than on whitespace.

SEE ALSO:
perldoc perlrun: how to execute the Perl interpreter: command line switches

Upvotes: 2

Related Questions