Reputation: 1271
How can I print a matched line as well as a line before and after it? I've currently got:
perl -lane 'print if $F[3] > 100000 && $F[2] =~ /^C$/ && print $last; $last = $_'
Which is capable of printing both the matched line and a line before it - but I am not sure how to include the line after.
Upvotes: 2
Views: 72
Reputation: 385655
The following handles overlapping matches. $N
is the number of lines to printe before and after the matching lines.
perl -lane'
BEGIN { $N = 1 }
if ($F[3] > 100000 && $F[2] =~ /^C$/) { print for splice(@buf), $_; $next=$N }
elsif ($next) { --$next; print }
else { push @buf, $_; splice @buf, 0, -$N }
'
Since we know $N = 1
, we can simplify the above into the following:
perl -lane'
if ($F[3] > 100000 && $F[2] =~ /^C$/) { print for splice(@buf), $_; $next=1 }
elsif ($next) { $next=0; print }
else { @buf = $_ }
'
Upvotes: 1
Reputation: 3535
You can also use seek
and tell
and rewind back one line for overlapping matches:
#!/usr/bin/perl
use strict;
use warnings;
open my $fh ,'<', 'input' or die "unable to open file: $!\n";
my $last="";
while(<$fh>){
my @b=split;
if(($b[3] > 100000) && ($b[2] =~ /^C$/)){
print $last if $last;
print;
my $t=tell $fh;
print scalar <$fh>,"\n";
seek $fh,$t,0; #rewind
}
$last=$_;
}
close($fh);
Upvotes: 0
Reputation: 241828
You can read the next line from the file directly using scalar <>
:
perl -lane 'print, print scalar <>
if $F[3] > 100000 && $F[2] =~ /^C$/
&& print $last;
$last = $_' input
Or use a sliding window for overlapping matches:
perl -ane 'BEGIN { @b = map [], 1 .. 3 }
sub out {
shift @b;
if ($b[1][3] > 100_000 && $b[1][2] =~ /^C$/) {
print for map $_->[-1], @b;
}
}
push @b, [@F, $_];
out()
}{ out() # Process the last line
' input
Upvotes: 4