#!/pgk/bin/perl -- # -*-Perl-*- # # ngrep - "near" grep, gives surrounding "context" # Author: Ron Maeder (maederr@cs.ucdavis.edu) # History: May 31, 1991 inital release # Modified by N Matloff, July 3, 2000. # Example: ngrep -a1 -b1 '^hel' /usr/dict/words # # Note: See code for interpretation of command line switches # $max_before = 4; # set defaults $max_after = 4; $TRUE = 1; # make the boolean flags obvious $FALSE = 0; $usage = "Usage: ngrep [-bxx] [-ayy] [-h] [-t] [-l] [-m] [-f] [-q] " . "[--] reg_expr [ filename... ]\n"; # while there are still switches to process ... while ($_ = $ARGV[0], /^-/) { # man page, pp. 14-15 shift; # get next arg last if /^--$/; # stop processing switches if get to "--" # if match -bxx then $max_before = xx if (/^-b(\d+)$/) { $max_before = $1; } elsif (/^-a(\d+)$/) { $max_after = $1; } elsif (/^-h$/) { $no_head_line_nums = $TRUE; } elsif (/^-t$/) { $no_tail_line_nums = $TRUE; } elsif (/^-l$/) { # no line numbers at all $no_head_line_nums = $TRUE; $no_tail_line_nums = $TRUE; } elsif (/^-m$/) { $no_match_info = $TRUE; } elsif (/^-f$/) { $no_filenames = $TRUE; } elsif (/^-q$/) { # quiet $no_head_line_nums = $TRUE; $no_tail_line_nums = $TRUE; $no_match_info = $TRUE; $no_filenames = $TRUE; } elsif (/^-d$/) { $debug = $TRUE; } # not documented in Usage else { print $usage; exit(1); } } unless ($reg_expr = shift) { # get regular expression to match print $usage; exit(1); } if ($debug) { print "max_before = $max_before\tmax_after = $max_after\t"; print "reg_expr = $reg_expr\n"; print "no_head_line_nums = $no_head_line_nums\n"; print "no_tail_line_nums = $no_tail_line_nums\n"; print "no_match_info = $no_match_info\n"; print "no_filenames = $no_filenames\n"; } # interate over all the files specified unshift(@ARGV, "-") if ($#ARGV < $[); # use stdin if no filenames..., p. 14 # this line suppresses filenames if there is only one to print $no_filenames = $no_filenames || ($#ARGV == $[); while ($grep_filename = shift) { unless (open(GREP_FILE, $grep_filename)) { print STDERR "Can't open $grep_filename: $!\n"; next; # skip this file... } $gap_in_output = $TRUE; # used to decide when to print line # $file_name_printed = $FALSE; while () { # if the pattern is matched... if (/$reg_expr/o) { # man page, p. 47 if ($gap_in_output) { $gap_in_output = $FALSE; unless ($file_name_printed) { print "**** $grep_filename ****\n"; $file_name_printed = $TRUE; } } # spit out the before buffer while ($bef = shift(@before_buf)) { print "b> " unless ($no_match_info); print $bef; } print "m> " unless ($no_match_info); print; # print the matched line # while there is still input, and "after" lines to print... for ($i = 0; ($i < $max_after) && ($_ = ); $i++) { if (/$reg_expr/o) { # matched again before done printing print "m> " unless ($no_match_info); print; # print the matched line $i = -1; # reset "after" counter, and continue } else { print "a> " unless ($no_match_info); print; # print the matched line } } } else { # if the pattern is NOT matched... # keep a buffer/queue of the last few lines seen push(@before_buf, $_); # man page, p. 55 # $#before_buf is index of last elt in @before_buf, length - 1 if ($#before_buf >= $max_before) { shift(@before_buf); # man page, p. 63 if (!$gap_in_output) { $gap_in_output = $TRUE; # if @before_buf overflowed... } } } } # if printed last line of file... unless ($gap_in_output || $no_tail_line_nums) { print "^^^^ ", ($. - ($#before_buf + 1)), " ^^^^\n"; } }