Hi
is there a way in grep to display few lines before and after the pattern??
I tried options A and B and after-context and before-context. But they don't work on Solaris platform.
please advise.
Hi
is there a way in grep to display few lines before and after the pattern??
I tried options A and B and after-context and before-context. But they don't work on Solaris platform.
please advise.
Try...
nawk 'c-->0;$0~s{if(b)for(c=b+1;c>1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=2 a=4 s="string" file1
...where "b" and "a" are the number of lines to print before and after string "s".
---edit----
It's not the best generic solution because it can't handle the case if the search string is repeated in the "before" lines.
A better way...
nawk '$0~s{for(c=NR-b;c<=NR+a;c++)r[c]=1}{q[NR]=$0}END{for(c=1;c<=NR;c++)if(r[c])print q[c]}' b=2 a=4 s="string" file1
...where "b" and "a" are the number of lines to print before and after string "s".
Hi Ygor,
Could you explain this awk code. I am a bit confused with this.
Regards,
Ranj
I do not know if it works on Solaris, I'm an AIX/Lnx. GNU grep has the feature '-A num' and '-B num' to display n rows before and/or after the pattern.
Here you go..
I can't remember where I found this, but it works really well.
#!/usr/bin/perl
#
# wgrep.pl - windowed grep utility
#
# Change Log
#----------------------------------------------------------------
# 13/11/2006 - Goran Script Created
#
use strict;
use IO::File;
use IO::Handle;
my ($before,$after,$show_stars,$show_nums,$sep,$show_fname);
my ($show_sep,$arg,$file,$regexp,$lnum,$fhandle,$nbef,$naft);
my ($matched,$matched2,@line_buf,@temp,$fh,$ret);
$before = 3; $after = 3; # default window size
$show_stars = 0;
$show_nums = 0;
$sep = "**********\n";
$show_fname = 1;
$show_sep = 1;
# loop until an argument doesn't begin with a "-"
while ($ARGV[0] =~ /^-(\w)(.*)/) {
$arg = $1; # $arg holds the option letter
if ($arg eq "s") { $show_stars = 1; }
elsif ($arg eq "n") { $show_nums = 1; }
elsif ($arg eq "m") { $show_fname = 0; }
elsif ($arg eq "d") { $show_sep = 0; }
elsif ($arg eq "w") {
# parse 2nd matched section at colon
@temp=split(/:/,$2);
$before = $temp[0] if $temp[0] ne '';
$after = $temp[1] if $temp[1] ne '';
}
elsif ($arg eq "p") {
$before = 0;
$after = 0;
$show_sep = 0; }
elsif ($arg eq "W") {
$before = 0;
$after = 0;
}
elsif ($arg eq "h") { &usage(""); }
else { &usage("wgrep: invalid option: $ARGV[0]");
} # end of if command
shift; # go on to next argument
} # end of foreach loop
&usage("wgrep: missing regular expression") if ! $ARGV[0];
$regexp = $ARGV[0];
shift;
$regexp =~ s,/,\\/,g; # "/" --> "\/"
# if no files are specified, use standard input
if (! @ARGV[0]) { @ARGV[0] = "STDIN"; }
LOOP:
foreach $file (@ARGV) { # loop over file list
if ($file eq "STDIN") {
$fh=new IO::Handle;
$ret=$fh->fdopen(fileno(STDIN),"r");
die "Can't open STDIN." unless $ret;
}
else {
$fh = new IO::File "$file", "r";
if (! defined $fh) {
print STDERR "Can't open file $file; skipping it.\n";
next LOOP; # jump to LOOP label
}
}
$lnum = 0;
$nbef = 0; $naft = 0;
$matched = 0; $matched2 = 0;
&clear_buf(0) if $before > 0;
while (<$fh>) { # loop over the lines in the file
++$lnum; # increment line number
if ($matched) { # we're printing the match window
if ($_ =~ /$regexp/) { # if current line matches pattern:
$naft = 0; # reset the after window count,
&print_info(1); # print preliminary stuff,
print $_; # and print the line
}
else { # current line does not match
if ($after > 0 && ++$naft <= $after) {
# print line anyway if still in the after window
&print_info(0); print $_;
}
else { # after window is done
$matched = 0; # no longer in a match
$naft = 0; # reset the after window count
# save line in before buffer for future matches
push(@line_buf, $_); $nbef++;
} # end else not in after window
} # end else curr. line not a match
} # end if we're in a match
else { # we're still looking for a match
if ($_ =~ /$regexp/) { # we found one
$matched = 1; # so set match flag
# print file and/or section separator(s)
print $sep if $matched2 && $nbef > $before && $show_sep && $show_fname;
print "********** $file **********\n" if ! $matched2++ && $show_fname;
# print and clear out before buffer and reset before counter
&clear_buf(1) if $before > 0; $nbef = 0;
&print_info(1);
print $_; # print current line
}
elsif ($before > 0) {
# pop off oldest line in before buffer & add current line
shift(@line_buf) if $nbef >= $before;
push(@line_buf,$_); $nbef++;
} # end elseif before window is nonzero
} # end else not in a match
} # end while loop over lines in this file
$fh->close;
} # end foreach loop over list of files
exit; # end of script proper
# subroutines #
sub print_info {
print $_[0] ? "* " : " " if $show_stars;
printf "%4d ", $lnum if $show_nums;
} # end subroutine print_info
sub clear_buf {
# argument says whether to print before window or not
my ($i,$j,$print_flag);
$print_flag = $_[0];
$i = 0; $j = 0;
if ($print_flag) {
# if we're printing line numbers, fiddle with the
# counter to account for the before window
if ($show_nums) {
$lnum -= ($#line_buf + 1);
}
while ($j <= $#line_buf) { # print before window
&print_info(0);
print $line_buf[$j++];
$lnum++ if $show_nums;
} # end while
} # end if print_flag
@line_buf = (); # clear line_buf array
} # end subroutine clear_buf
sub usage {
# optional argument is an additional message line
print STDERR $_[0],"\n" if $_[0];
print STDERR "Usage: wgrep [-n] [-w[:A] | -W] ";
print STDERR "[-d] [-p] [-s] [-m] regexp file(s)\n";
print STDERR " -n = number lines\n";
print STDERR " -s = mark matched lines with asterisks\n";
print STDERR " -wB:A = display B lines before and A lines after\n";
print STDERR " each matched line [both default to 3]\n";
print STDERR " -W = suppress window; equivalent to -w0:0\n";
print STDERR " -d = suppress separation lines between sections\n";
print STDERR " -m = suppress file name header lines\n";
print STDERR " -p = plain mode: equivalent to -W -d\n";
print STDERR " -h = print this help message and exit\n";
print STDERR "Note: If present, -h prevails; otherwise, the rightmost\n";
print STDERR " option wins in the case of contradictions.\n";
exit;
}
Here's an example of how I have used wgrep on one of our Sunfire v440 servers
[tst1/] uname -a
SunOS tst1 5.9 Generic_112233-10 sun4u sparc SUNW,Sun-Fire-V440
[tst1/] prtpicl -v -c temperature-sensor | wgrep -w0:6 HighPowerOffThreshold | grep -v Low
********** STDIN **********
:HighPowerOffThreshold 120
:HighShutdownThreshold 102
:HighWarningThreshold 97
:Temperature 43
**********
:HighPowerOffThreshold 120
:HighShutdownThreshold 102
:HighWarningThreshold 97
:Temperature 45
**********
:HighPowerOffThreshold 75
:HighShutdownThreshold 65
:HighWarningThreshold 60
:Temperature 25
**********
:HighPowerOffThreshold 75
:HighShutdownThreshold 65
:HighWarningThreshold 60
:Temperature 25
**********
:HighPowerOffThreshold 62
:HighShutdownThreshold 52
:HighWarningThreshold 47
:Temperature 21
**********
:HighPowerOffThreshold 85
:HighShutdownThreshold 75
:HighWarningThreshold 65
:Temperature 27
[tst1/]
This is exactly what I needed.
Thank you so much.
awk:
nawk -v ran=$1 -v pat=$2 '{
arr[NR]=$0
if (index($0,pat)!=0)
line=NR
}
END{
for(i=line-ran;i<=line+ran;i++)
print arr
}' file
perl:
$pat=shift;
$ran=shift;
open FH,"<a";
while(<FH>){
$arr[$.]=$_;
if (index($_,$pat)>=0){
$line=$.;
}
}
close(FH);
for($i=$line-$ran;$i<=$line+$ran;$i++)
{
print $arr[$i];
}
Perfect!!.. This is what I was looking for. Thanks!
awesome!!!
nawk 'c-->0;$0~s{if(b)for(c=b+1;c>1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=2 a=4 s="string" file1
This one liner really helped me to get what I want but there is little deviant to my problem...
I want to search for a string and go back several lines(the number of lines is not fixed) and catch a pattern which is associated with the searched string.
for eg:
<HEADER>
line1
line2
line3
line4
............
<string>
I want to somehow associate <HEADER> line once I find my <string> and discard the rest of results..As I said, the number of lines is not fixed till we traverse back to <HEADER> line.
Is there any way we can achieve this?.
-Anduzzi
Try...
awk '$0~s,$0~t' s="<HEADER>" t="<string>" file1
Could you please explain the command and for some reason the syntax doesnt quite work for me ?.
Thx !