In Perl can i apply 'grep' command on the data i captured using flip-flop operator directly?

StackOverflow https://stackoverflow.com/questions/8702136

  •  12-04-2021
  •  | 
  •  

Question

I need to find the 'number' of occurrences of particular words (C7STH, C7ST2C) that come in the output of a command. The command starts and ends with a 'fixed' text - START & END like below. This command is repeated many times against different nodes in the log file.

...

START
SLC ACL PARMG ST                   SDL                             SLI
 0  A1  17    C7STH-1&&-31         MSC19-0/RTLTB2-385
 1  A1  17    C7STH-65&&-95        MSC19-0/RTLTB2-1697

SLC ACL PARMG ST                   SDL                             SLI
 0  A2   0    C7ST2C-4             ETRC18-0/RTLTB2-417
 1  A2   0    C7ST2C-5             ETRC18-0/RTLTB2-449
 2  A2   0    C7ST2C-6             ETRC18-0/RTLTB2-961
...
END

....

I am using flip-flop operator (if (/^START$/ .. /^END$/)to get each command output. Now

  1. Is there a way to do 'grep' on this data without going line by line? Like can i get all the text between 'START' and 'END' into an array and do 'grep' on this etc?

  2. Also is it 'ok' to have multiple levels of if blocks with flip-flop operator from performance point of view?

Was it helpful?

Solution

Maybe your looking for something along these lines:

#!/usr/bin/env perl
use strict;
use warnings;
my $word = q(stuff);
my @data;
while (<DATA>) {
    if ( /^START/../^END/ ) {
        chomp;
        push @data, $_ unless /^(?:START|END)/;
    }
    if ( /^END/ ) {
        my $str = "@data";
        print +(scalar grep {/$word/} (split / /,$str)),
            " occurances of '$word'\n";
        @data = ();     
    }
}
__DATA__
this is a line
START of my stuff
more my stuff
and still more stuff
and lastly, yet more stuff
END of my stuff
this is another line
START again
stuff stuff stuff stuff
yet more stuff
END again

...which would output:

3 occurances of 'stuff'
5 occurances of 'stuff'

OTHER TIPS

This would be a simple solution:

my $number = grep {/particular word/} grep {/START/../END/} <>;

(Since you don't provide a code sample I've used the diamond operator and assumed the log file is passed as an argument to the script. Replace with file handle if needed.)

grep {/START/../END/} <> creates a list of elements within and including the delimiters, and grep {/particular word/} works on that list.

From a performance point of view you'd be better off with

for (<>) {
    $number++ if /START/../END/ and /a/;
}

Note that you have to use and instead of && or wrap your flip-flop expression in parentheses because of operator precedence.

Combining both:

my $number = grep {/START/../END/ and /particular word/} <>;

Like can i get all the text between 'START' and 'END' into an array and do 'grep' on this etc?

(push @ar,$_) if /START/ .. /END/;
grep {/word/ @ar};

Also is it 'ok' to have multiple levels of if blocks with flip-flop operator from performance point of view?

As long as you are not working for NASA.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top