From pa.dec.com!decwrl!sdd.hp.com!samsung!uunet!sparky!kent Tue Jul 16 09:10:23 PDT 1991
Article: 2478 of comp.sources.misc
Xref: pa.dec.com comp.sources.misc:2478 comp.lang.perl:5969
Path: pa.dec.com!decwrl!sdd.hp.com!samsung!uunet!sparky!kent
From: prechelt@i41s14.ira.uka.de (Lutz Prechelt)
Newsgroups: comp.sources.misc,comp.lang.perl
Subject: v20i088:  cgrep - context grep in perl, Part01/01
Message-ID: <1991Jul3.010431.25463@sparky.IMD.Sterling.COM>
Date: 3 Jul 91 01:04:31 GMT
Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield)
Reply-To: prechelt@i41s14.ira.uka.de (Lutz Prechelt)
Organization: University of Karlsruhe, FRG
Lines: 242
Approved: kent@sparky.imd.sterling.com
X-Md4-Signature: 08347b693b1d098eaac6eb4df1a75ee0

Submitted-by: Lutz Prechelt <prechelt@i41s14.ira.uka.de>
Posting-number: Volume 20, Issue 88
Archive-name: cgrep/part01

The following is a version of grep (as a Perl script)
that gives you a number of context lines along with the 
matching line. It was inspired by Larry Walls example from
the perl book. The context size is selectable.

The program has several options; in particular there is an 
especially useful 'paragraph mode' where
the context is broken off at an empty line.

For exact usage, see the message in the body of the script.
You will probably have to edit the first line of the script,
to tell it where your 'perl' resides.

   Lutz

Lutz Prechelt   (++49/721/608-4317,  FAX: ++49/721/697760)
Institut fuer Programmstrukturen und Datenorganisation
Universitaet Karlsruhe;  D-7500 Karlsruhe 1;  Germany
prechelt@ira.uka.de  or  prechelt!ira.uka.de@relay.csnet
--------------------------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents:  cgrep
# Wrapped by kent@sparky on Tue Jul  2 19:56:51 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive."'
if test -f 'cgrep' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cgrep'\"
else
  echo shar: Extracting \"'cgrep'\" \(4771 characters\)
  sed "s/^X//" >'cgrep' <<'END_OF_FILE'
X#!/bin/perl
X#
X#    Copyright (C) 1991 by Lutz Prechelt, Karlsruhe
X#
X#    This program is free software; you can redistribute it and/or modify
X#    it under the terms of the GNU General Public License as published by
X#    the Free Software Foundation; either version 1, or (at your option)
X#    any later version.
X#    This program is distributed in the hope that it will be useful,
X#    but WITHOUT ANY WARRANTY; without even the implied warranty of
X#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X#    GNU General Public License for more details.
X#    If you don't have a copy of the GNU General Public License write to
X#    Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
X# Author: Lutz Prechelt (prechelt@ira.uka.de),
X#         23.03.91
X# Change: Lutz Prechelt, 02.07.91
X#
X# Usage: see message at "die" below.
X
X$infinity = 10000;
X
X$precontext  = 2;
X$postcontext = 2;
X$paragraphmode    = 0;
X$withlinenumber   = 0;
X$withfilename     = 0;
X$wrong_option     = 0;
X$reversemode      = 0;
X$delimiterstring  = "-----------\n";
X# $endpara = '\S.*\n';
X
Xsub showline {
X  if ($withfilename != 0) {
X    printf ("\"%s\"", $ARGV);
X  }
X  if ($withfilename != 0 && $withlinenumber != 0) {
X    print ",";
X  }
X  if ($withlinenumber != 0) {
X    printf ("%4d", $.);
X  }
X  if ($withfilename != 0 || $withlinenumber != 0) {
X    print ": ";
X  }
X  print ($_[0]);
X}
X
X
X# Process the Options:
Xdo {
X  $something_done = 1;
X  if ($ARGV[0] =~ /^-(\d+)$/) {
X    $precontext = $postcontext = $1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-(\d+)[\,\+\/\;](\d+)$/) {
X    $precontext  = $1;
X    $postcontext = $2;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-d$/ && $#ARGV > 0) {
X    $delimiterstring = $ARGV[1];
X    $delimiterstring =~ s/\\n/\n/o;
X    shift; shift;
X  }
X  elsif ($ARGV[0] =~ /^-d(.*)$/) {
X    $delimiterstring = $1;
X    $delimiterstring =~ s/\\n/\n/o;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-p$/) {
X    $paragraphmode = 1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-n$/) {
X    $withlinenumber = 1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-h$/) {
X    $withfilename = 1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-v$/) {
X    $reversemode = 1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-e$/) { # end options (for expressions starting with - )
X    $something_done = 0;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-/) {
X    printf ("don't know option '%s'\n", $ARGV[0]);
X    $wrong_option = 1;
X    $something_done = 0;
X    shift;
X  }
X  else {
X    $something_done = 0;
X  }
X} while ($something_done);
X
X
X# Usage message:
Xif ($#ARGV == -1 || $wrong_option) {
X  die "
X   Usage: cgrep [-pre[,post]] [-p] [-v] [-h] [-n] [-d string] pattern
X[file...]
X
X   cgrep is a context grep. It displays more than the one matching line for
X   every match (2 before and 2 after as default).
X
X   -3  means display 3 lines before and 3 lines after the match
X   -5,12  means display 5 lines before the match and 12 lines after
X   -p  means display only as much of the context as belongs to the
X       current paragraph. (paragraphs bounded by empty lines)
X   -v  means invert search (display nomatches)
X   -h  means toggle display filename before every line
X   -n  means display line number before every line
X   -d string  means use string as the output delimiter string
X   pattern  is a Perl regular expression (you better quote it !)
XExiting";
X}
X
X
Xif (length (@ARGV) > 1) {
X  $withfilename = !$withfilename;
X}
X
X
X# Get the pattern and protect the delimiter.
X$pat = shift;
X$pat =~ s#/#\\/#g;
X
X
X# current line will always be at end of array, i.e. $ary[$currentpre]
X$_ = <>;
Xpush(@ary,$_);
X$currentpre = 0;
X
X
X# now use @ary as a silo, shifting and pushing.
X# the length of the @ary at any time is $currentpre + 1
X# the current line is @ary[$currentpre], the postcontext is not held in @ary.
X$seq = 0;
X$lastoutput = $infinity;  #last output is infinitely many lines ago
X$cur = @ary[0];       #current line
Xwhile ($cur) {  #as long as there is something to look at
X  if ($reversemode == 1 ? $cur !~ /$pat/o : $cur =~ /$pat/o) {   #match found
X    if ($lastoutput <= $postcontext) {
X      &showline ($cur);
X    }
X    else {
X      print $delimiterstring if ($seq++ && $precontext + $postcontext > 0);
X      foreach $line (@ary) {
X        &showline ($line);
X      }
X    }
X    $lastoutput = 0;
X  }
X  elsif (($cur !~ /\S.*\n/o && $paragraphmode == 1) || eof) {
X#paragraph/file end
X    for (; $currentpre >= 0; $currentpre--) {
X      shift (@ary);
X    }
X    $lastoutput = $infinity;
X    close (ARGV) if (eof);
X  }
X  elsif ($lastoutput <= $postcontext) {     #another line of postcontext
X    &showline ($cur);
X  }
X  #goto next line of input:
X  $lastoutput++;
X  $_ = <> if $_;
X  push(@ary,$_); 
X  if ($currentpre < $precontext) {
X    $currentpre++;
X  }
X  else {
X    shift(@ary);
X  }
X  $cur = $ary[$currentpre];
X}
X
X
X
END_OF_FILE
  if test 4771 -ne `wc -c <'cgrep'`; then
    echo shar: \"'cgrep'\" unpacked with wrong size!
  fi
  chmod +x 'cgrep'
  # end of 'cgrep'
fi
echo shar: End of archive.
exit 0
exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.


