grep and display few lines before and after | Unix Linux Forums | Solaris

  Go Back    


Solaris The Solaris Operating System, usually known simply as Solaris, is a Unix-based operating system introduced by Sun Microsystems. The Solaris OS is now owned by Oracle.

grep and display few lines before and after

Solaris


Tags
perl, perl shift, shift, shift perl, solaris

Closed Thread    
 
Thread Tools Search this Thread Display Modes
    #1  
Old 12-07-2006
melanie_pfefer melanie_pfefer is offline
Registered User
 
Join Date: Nov 2006
Last Activity: 25 September 2009, 6:39 AM EDT
Posts: 234
Thanks: 0
Thanked 0 Times in 0 Posts
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.
Sponsored Links
    #2  
Old 12-07-2006
Ygor's Avatar
Ygor Ygor is offline Forum Advisor  
Advisor
 
Join Date: Oct 2003
Last Activity: 2 May 2014, 7:14 AM EDT
Location: 54.23, -4.53
Posts: 1,801
Thanks: 1
Thanked 111 Times in 98 Posts
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.
The Following 4 Users Say Thank You to Ygor For This Useful Post:
doublefrangelic (10-18-2010), nariwithu (01-25-2012), nes (11-28-2013), shandrio (07-23-2012)
Sponsored Links
    #3  
Old 01-03-2007
ranj@chn ranj@chn is offline Forum Advisor  
Registered User
 
Join Date: Oct 2005
Last Activity: 25 August 2011, 2:35 AM EDT
Location: Chennai
Posts: 370
Thanks: 0
Thanked 5 Times in 4 Posts
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
makki makki is offline
Registered User
 
Join Date: Jan 2007
Last Activity: 25 February 2007, 3:05 PM EST
Location: Vac, Hungary
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
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.
Sponsored Links
    #5  
Old 01-03-2007
Tornado's Avatar
Tornado Tornado is offline Forum Advisor  
Registered User
 
Join Date: Nov 2006
Last Activity: 23 October 2013, 9:08 PM EDT
Location: Melbourne
Posts: 261
Thanks: 1
Thanked 11 Times in 8 Posts
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;
}

Sponsored Links
    #6  
Old 01-03-2007
Tornado's Avatar
Tornado Tornado is offline Forum Advisor  
Registered User
 
Join Date: Nov 2006
Last Activity: 23 October 2013, 9:08 PM EDT
Location: Melbourne
Posts: 261
Thanks: 1
Thanked 11 Times in 8 Posts
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/]

Sponsored Links
    #7  
Old 06-09-2008
Primate Primate is offline
Registered User
 
Join Date: Jun 2008
Last Activity: 9 June 2008, 7:25 PM EDT
Posts: 1
Thanks: 0
Thanked 1 Time in 1 Post
Quote:
Originally Posted by Ygor View Post
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.
The Following User Says Thank You to Primate For This Useful Post:
yashid (07-29-2010)
Sponsored Links
Closed Thread

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

More UNIX and Linux Forum Topics You Might Find Helpful
Thread Thread Starter Forum Replies Last Post
Using grep and zgrep then display the next few lines khestoi UNIX for Dummies Questions & Answers 10 08-27-2010 11:19 PM
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



All times are GMT -4. The time now is 10:21 PM.