grep and display few lines before and after


Login or Register to Reply

 
Thread Tools Search this Thread
# 1  
Old 12-07-2006
grep and display few lines before and after

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.
# 2  
Old 12-07-2006
Try...
Code:
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...
Code:
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".

Last edited by Ygor; 05-31-2012 at 07:51 AM.. Reason: Had to update this post because my buggy code is propagating all over the internet.
These 6 Users Gave Thanks to Ygor For This Post:
doublefrangelic (10-18-2010) mad man (01-25-2016) nariwithu (01-25-2012) nes (11-28-2013) shandrio (07-23-2012) Sionnagh (10-06-2014)
# 3  
Old 01-03-2007
little explanation required

Hi Ygor,

Could you explain this awk code. I am a bit confused with this.

Regards,
Ranj
# 4  
Old 01-03-2007
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.
# 5  
Old 01-03-2007
Here you go..
I can't remember where I found this, but it works really well.
Code:
#!/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[B][: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;
}

Tornado
# 6  
Old 01-03-2007
Here's an example of how I have used wgrep on one of our Sunfire v440 servers
Code:
[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/]

Tornado
# 7  
Old 06-09-2008
Quote:
Originally Posted by Ygor
Try...
Code:
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".
This is exactly what I needed.
Thank you so much.
This User Gave Thanks to Primate For This Post:
yashid (07-29-2010)
Login or Register to Reply

|
Thread Tools Search this Thread
Search this Thread:
Advanced Search

More UNIX and Linux Forum Topics You Might Find Helpful
Display lines for a particular year in a file using grep skoshekay Shell Programming and Scripting 2 01-04-2018 06:24 PM
Grep and display multiple lines Junaid Subhani Shell Programming and Scripting 3 04-13-2016 02:23 PM
Grep pattern and display all lines below venkidhadha Shell Programming and Scripting 5 06-17-2014 06:59 AM
Grep multiple exact match, do not display lines rajeshwebspere Shell Programming and Scripting 4 01-21-2014 09:50 PM
Grep word after last occurance of string and display next few lines nes Shell Programming and Scripting 17 12-22-2013 11:52 PM
Grep couple of consecutive lines if each lines contains certain string black_fender Shell Programming and Scripting 14 05-31-2012 05:17 AM
AWK/GREP: grep only lines starting with integer chrisjorg Shell Programming and Scripting 2 04-17-2012 10:06 AM
Perl XML, find matching condition and grep lines and put the lines somewhere else tententen Shell Programming and Scripting 4 11-03-2010 08:55 PM
Using grep and zgrep then display the next few lines khestoi UNIX for Dummies Questions & Answers 10 08-27-2010 11:19 PM
AIX equivalent to GNU grep's -B and -A [print lines after or before matching lines] slashdotweenie Shell Programming and Scripting 4 04-28-2010 11:52 AM
grep and display lines from a file user7617 Shell Programming and Scripting 6 08-27-2009 11:41 PM
Grep and display n lines after the match is found. cv_pan UNIX for Dummies Questions & Answers 3 09-25-2008 11:15 PM
Help with "grep", need to display several lines Draken UNIX for Dummies Questions & Answers 9 04-04-2008 03:46 AM
Make grep -c display like grep -n? Jerrad Shell Programming and Scripting 2 08-25-2006 12:20 AM
Grep and display bobo UNIX for Dummies Questions & Answers 4 06-19-2006 02:42 PM