Visit Our UNIX and Linux User Community


grep and display few lines before and after


 
Thread Tools Search this Thread
Operating Systems Solaris grep and display few lines before and after
# 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 08: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:
# 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:

Previous Thread | Next Thread
Test Your Knowledge in Computers #250
Difficulty: Easy
MILNET was the name given to a network that split off from ARPANET in 1983 to create an internetwork designated for use by the U.S. Department of Defense.
True or False?

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Display lines for a particular year in a file using grep

hi, I have a log file with data for more than 3 years, i want only the rows for the year 2017, say for example. My file has the data like this 08-OCT-2015 11:17:35 AAA, BBBB 08-OCT-2017 11:17:35 AAA,Bdfdfd,dfdfd,dfd 08-Nov-2017 11:17:35 AAA,Bdfdfd,dfdfd,deree i want the rows... (2 Replies)
Discussion started by: skoshekay
2 Replies

2. Shell Programming and Scripting

Grep and display multiple lines

Hi guys, I have a log file that generates multiple logs about a query. <query time='2016-04-13 13:01:50.825'> <PagingRequestHandler> <Before>brand:vmu</Before> <After>brand:vmu</After> </PagingRequestHandler> <GroupDeviceFilterHandler> <Before>brand:vmu</Before> ... (3 Replies)
Discussion started by: Junaid Subhani
3 Replies

3. Shell Programming and Scripting

Grep pattern and display all lines below

Hi I need to grep for a patter and display all lines below the pattern. For ex: say my file has the below lines file1 file2 file3 file4 file5 I NEED to grep for patter file3 and display all lines below the pattern. do we have an option to get this data. Let me know if you require... (5 Replies)
Discussion started by: venkidhadha
5 Replies

4. Shell Programming and Scripting

Grep multiple exact match, do not display lines

Hi, Need help to grep the following from a file x. I just want to grep exact match not lines and not partial word. CONFSUCCESS CONFFAIL CONFPARTIALSUCCESS >cat x xczxczxczc zczczcxx CONFSUCCESS czczczcczc czxxczxzxczcczc CONFFAIL xczxczcxcczczc zczczczcz CONFPARTIALSUCCESS czczxcxzc ... (4 Replies)
Discussion started by: rajeshwebspere
4 Replies

5. Shell Programming and Scripting

Grep word after last occurance of string and display next few lines

Hi, I wanted to grep string "ERROR" and "WORNING" after last occurrence of String "Starting" only and wanted to display two lines after searched ERROR and WORNING string and one line before. I have following cronjob log file "errorlog" file and I have written the code for same in Unix as below... (17 Replies)
Discussion started by: nes
17 Replies

6. UNIX for Dummies Questions & Answers

Using grep and zgrep then display the next few lines

Hello everyone. I would like to know if I can use grep or zgrep to search for a particular pattern then print the x number of lines after the pattern was found. Lets say for example a pattern was found on line 3, I wanted the output to show lines 3, 4 and 5. Thanks! (10 Replies)
Discussion started by: khestoi
10 Replies

7. Shell Programming and Scripting

grep and display lines from a file

I have to grep on a few words in a file and then display the line containing those words and the line above it. For ex - File1.txt contains... abc xyz abc This is a test Test successful abc xyz abc Just a test Test successful I find the words 'Test successful' in the file... (6 Replies)
Discussion started by: user7617
6 Replies

8. UNIX for Dummies Questions & Answers

Grep and display n lines after the match is found.

Hello, How do I use grep to find a pattern in a list of file and then display 5 lines after the pattern is matched Eg: I want to match the string GetPresentCode in all files in a folder and then see 4 lines following this match. I am not sure if grep is what should be used to achieve. Thanks!... (3 Replies)
Discussion started by: cv_pan
3 Replies

9. UNIX for Dummies Questions & Answers

Help with "grep", need to display several lines

I have a file from which I need to collect lines to another file. I know how to use 'grep' for this, but I don't know how to do when I wan't several lines after the search word, and the amount of lines I need varies from case to case. The file I search in looks something like this: >8534734... (9 Replies)
Discussion started by: Draken
9 Replies

10. Shell Programming and Scripting

Make grep -c display like grep -n?

Hey Guys, Wondering if there is a way to do the following I have a file called test.txt abc def abc abc def I have a pattern file called pattern.txt containing the following abc def I want to do a count, but have it display the count value preceeding each line like grep -n (2 Replies)
Discussion started by: Jerrad
2 Replies

Featured Tech Videos