From pa.dec.com!nntpd.lkg.dec.com!news.crl.dec.com!deccrl!caen!zaphod.mps.ohio-state.edu!samsung!uunet!sparky!kent Tue Jul 16 09:11:06 PDT 1991
Article: 2483 of comp.sources.misc
Xref: pa.dec.com comp.sources.misc:2483 comp.lang.perl:6052
Path: pa.dec.com!nntpd.lkg.dec.com!news.crl.dec.com!deccrl!caen!zaphod.mps.ohio-state.edu!samsung!uunet!sparky!kent
From: prechelt@i41s14.ira.uka.de (Lutz Prechelt)
Newsgroups: comp.sources.misc,comp.lang.perl
Subject: v20i092:  cgrep2 - context grep in perl, version 2, Part01/01
Keywords: context grep
Message-ID: <1991Jul10.020543.17296@sparky.IMD.Sterling.COM>
Date: 10 Jul 91 02:05:43 GMT
Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield)
Reply-To: prechelt@i41s14.ira.uka.de (Lutz Prechelt)
Organization: University of Karlsruhe, FRG
Lines: 300
Approved: kent@sparky.imd.sterling.com
X-Md4-Signature: fe1e3f8fb41eb9bf8df21657e63d1554

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

A few days ago I posted 'cgrep', Version 1.
I got some feedback since then and worked over it;
here is an upgrade. I think this will do for a while.

HERE WE GO:

The following is version 2 of cgrep (a Perl script).
cgrep is a grep that gives you a number of context lines along with the 
matching line.

The following changes occured in respect to version 1:

  I added options
    -i (ignore case)
    -c (count matches also)

  documented option
    -e (end the list of options)

  removed a bug in option
    -n which gave wrong line numbers in precontext

  and polished all a bit.

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
----------------------------- cut here -----------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  cgrep
# Wrapped by prechelt@Djibouti on Mon Jul  8 12:49:40 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cgrep' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cgrep'\"
else
echo shar: Extracting \"'cgrep'\" \(5904 characters\)
sed "s/^X//" >'cgrep' <<'END_OF_FILE'
X#!/tools/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# Version:     2,  Patchlevel 0
X# Author:      Lutz Prechelt (prechelt@ira.uka.de), 23.03.91
X# Correction   by Sridhar Vasudevan, 03.07.91
X# Last Change: Lutz Prechelt, 04.07.91
X#
X# Usage: see message at "die" below.
X
X#---------- constants:
X$infinity         = 10000;
X
X#---------- Variables:
X$delimiterstring  = "-----------\n";
X$matches          = 0;
X$precontext       = 2;
X$postcontext      = 2;
X$wrong_option     = 0;
X
X#---------- boolean Options:
X$paragraphmode    = 0;
X$count_matches    = 0;
X$ignorecase       = 0;
X$withlinenumber   = 0;
X$withfilename     = 0;
X$reversemode      = 0;
X
X# $endpara = '\S.*\n';
X
X#---------- Subroutines:
X
Xsub match_found {
X  #bad style: uses the global variables $ignorecase, $reversemode, $cur, $pat
X  if ($ignorecase != 0) {
X    ($reversemode == 1 ? $cur !~ /$pat/io : $cur =~ /$pat/io);
X  }
X  else {
X    ($reversemode == 1 ? $cur !~ /$pat/o : $cur =~ /$pat/o);
X  }
X}
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", $_[1]);
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] =~ /^-c$/) {
X    $count_matches = 1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-h$/) {
X    $withfilename = 1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-i$/) {
X    $ignorecase = 1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-n$/) {
X    $withlinenumber = 1;
X    shift;
X  }
X  elsif ($ARGV[0] =~ /^-p$/) {
X    $paragraphmode = 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] [-c] [-h] [-n] [-d string] 
X                [-e] pattern [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 (e.g.)
X   -5,12  means display 5 lines before the match and 12 lines after (e.g.)
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   -c   means display number of matching lines at the end of run
X   -h   means toggle display filename before every line
X   -i   means ignore case when matching the regexp
X   -n   means display line number before every line
X   -d string  means use string as the output delimiter string
X   -e   means end options (i.e. now comes the pattern, 
X                           for patterns starting with - )
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#---------- do the search
X# 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 (&match_found()) {
X    $matches++;
X    if ($lastoutput <= $postcontext) {
X      &showline ($cur, $.);
X    }
X    else {
X      print $delimiterstring if ($seq++ && $precontext + $postcontext > 0);
X      $lineno = $. - $#ary;
X      foreach $line (@ary) {
X        &showline ($line, $lineno++);
X      }
X    }
X    $lastoutput = 0;
X  }
X  elsif (($cur !~ /\S.*\n/o && $paragraphmode == 1) || eof) {
#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#---------- perhaps display number of matches:
Xif ($count_matches != 0) {
X  printf ("%d\n", $matches);
X}
X
X
END_OF_FILE
if test 5904 -ne `wc -c <'cgrep'`; then
    echo shar: \"'cgrep'\" unpacked with wrong size!
fi
chmod +x 'cgrep'
# end of 'cgrep'
fi
echo shar: End of shell 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.


