Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl script to extract 2 lines before and after the pattern matching

Tags:

perl

my file is like

line 1 
line 2 
line 3
target
line 5
line 6
line 7

I can write a regex that matches the target. What all I need is I need to grab lines 2,3,5,6. Is there any way to do it?

like image 308
LSivilia Avatar asked May 08 '11 13:05

LSivilia


People also ask

How do I get the matched pattern in Perl?

m operator in Perl is used to match a pattern within the given text. The string passed to m operator can be enclosed within any character which will be used as a delimiter to regular expressions.

How do I see the next line in Perl?

If you really want to get compact, you could do my $next = <$fh>; while(my $line = $next) { $next = <$fh>; ... }

How do I match a number in Perl?

Digit \d[0-9]: The \d is used to match any digit character and its equivalent to [0-9]. In the regex /\d/ will match a single digit.

What is pattern in Perl?

Perl Pattern Matching. Patterns are subject to an additional level of interpretation as a regular expression. This is done as a second pass, after variables are interpolated, so that regular expressions may be incorporated into the pattern from the variables.


3 Answers

If you're not determined to use perl you can easily extract the context you want with grep and Context Line Control options

grep -A 2 -B 2 target filename | grep -v target

Of course target will need to be replaced by a suitable regex.

like image 155
pavium Avatar answered Sep 22 '22 01:09

pavium


Robert is on the right path. You have to multiline your regex and match the 2 previous and next lines:

#!/usr/bin/perl -w

my $lines = <<EOF
line 1
line 2
line 3
target
line 5
line 6
line 7
EOF
;

# Match a new line, then 2 lines, then target, then 2 lines.
#                { $1       }        { $3       }
my $re = qr/^.*\n((.*?\n){2})target\n((.*?\n){2}).*$/m;

(my $res = $lines) =~ s/$re/$1$3/;
print $res;
like image 36
Mel Avatar answered Sep 20 '22 01:09

Mel


@lines = ('line 1', 'line 2', 'line 3', 'target', 'line 5', 'line 6', 'line 7');
my %answer;
$regex = 'target';
for my $idx (0..$#lines) {
    if ($lines[$idx] =~ /$regex/) {
        for $ii (($idx - 2)..($idx + 2)){
            unless ($lines[$ii] =~ /^$regex$/) {$answer{$ii} = $lines[$ii];}
        }
    }
}
foreach $key (sort keys %answer) { print "$answer{$key}\n" }

Which yields...

[mpenning@Bucksnort ~]$ perl search.pl
line 2
line 3
line 5
line 6
[mpenning@Bucksnort ~]$

EDIT

Fixed for @leonbloy's comment about multiple target strings in the file

like image 41
Mike Pennington Avatar answered Sep 22 '22 01:09

Mike Pennington