Subject: mg 1.2 (Re: want: context grep)

From: [email-masked] (Kazumasa Utashiro)
Date: Mon, 24 Feb 1992 03:28:57 GMT

In article <[email-masked]>
	[email-masked] (Paul O'Keefe) writes:
>Anyone have a grep that displays the lines surrounding a match?

I posted a command called 'mg' several month ago on this
newsgroup, and you can use it for this purpose.  But it's
probably overfeatured and not effective for your requirment.
I think some programs only for this purpose was posted, and
it is not so difficult to make .

I made some changes after last release.  Here is the latest
version.

Option -c interpretation was slightly changed.  To display 2
lines before and after matched line, use -c3 option now.
Default is -c1,1.  Option -c0 can be used to display matched
string only.

Option -c and -o (paragraph mode) works together.

New option -N was added to print byte offset.

New option -B was added to search string from binary file.

See 'mg -h' and build-in manual for detail. (There is
undocumented option -H which was called -N on last version
:-).  I'm not sure this works on any machine.)

---
K. Utashiro
[email-masked], [email-masked]

======================================================================
#!/usr/local/bin/perl
'di';
'ig00';
;#
;# mg: multi-line grep
;#
;# Copyright (c) 1991,1992 Kazumasa Utashiro <[email-masked]>
;# Original: Mar 29 1991
;; $rcsid = '$Header: /cvs/cvsfiles/sysadmin/homedir/projects/perl/mg.mail,v 1.1 2000/03/27 07:34:26 eichin Exp $';
;#
;# Usage:
;#	% mg 'internet control message protocol' rfc*.txt
;#	% mg -nRTP '*.[sch]' 'struct vnode' /sys
;#	% mg -o sockaddr /usr/include/sys/socket.h
;#	% mg -B '@(#)' /bin/awk
;#	% mg -iTB copyright /bin/*
;#	% echo $path | mg -Q mh
;#	etc.
;#
require('getopts.pl');
#require('usage.pl');
$opts = 'ilnNhwv:eEc:oO:g:C:ubqQYas2RP:V:FTBLSmMf:p:xzdIHX'; @opts = (
	'-:dIHXY:',
	'i::ignore case',
	'l::list filename only',
	'n::print line number',
	'N::print byte offset',
	'h::do not display filenames',
	'w::space doesn\'t match null ("a b" matches "ab" by default)',
	'v:pattern:skip the line if matched with exp (w/o -a, -l)',
	'e::use pattern as regular expression (space is special)',
	'E::use pattern as regular expression completely',
	'c:n[,n]|/\d+(,\d+)?/:print n tol/eol before/after matched line',
	'o::paragraph mode',
	'O:string:specify paragraph delimiter string',
	'g:lines|/^\d+$/:page mode',
	'C:chars:continuous characters',
	'u::underline matched string (except JIS)',
	'b::make bold (print twice) matched string (except JIS)',
	'q::quote matched string (except JIS)',
	'Q::stand-out matched string (except JIS)',
	'Y::yield to -Q option even if stdout is not a terminal',
	'a::print whole file (no filename and line number)',
	's::output filename and line number separately',
	'2::duplicate line if multiple matching is occured',
	'R::search recursively',
	'P:pattern:specify search file in wildcard (w/-R)',
	'V:pattern:specify exception file in wildcard (w/-R)',
	'F::follow symbolic link of directory (w/-R)',
	'T::search text file only',
	'B::search from binary file',
	'L::print formfeed before each matching',
	'S::get filenames from stdin',
	'm::print only splited line',
	'M::print only multiple matched line',
	'f:file:file contains search pattern',
	'p:pattern:specify search pattern',
	'x::print processing filename',
	'z::do not uncompress automatically',
);
sub usage {
    @usage = &Usage($0, $opts, "pattern [ file ... ]", @opts);
    print "usage: mg [ -options ] pattern [ file... ]\n", pop(@usage);
    print "$rcsid\n" if $rcsid =~ /:/;
    exit 2;
}
($_ = $ENV{'MGOPTS'}) && do { s/^[^-]/-$&/; unshift(@ARGV, $_); };
&Getopts($opts) || &usage;

$opt_X && ($_ = join('','a'..'z',"\n",'A'..'Z',"\n"), eval "tr/$opts/./", die);
exec "nroff -man $0|" .($ENV{'PAGER'}||'more'). " -s" if $opt_H;
$opt_C =~ s/\W/\\$&/g, $opt_C = "[\\s$opt_C]" if $opt_C;
$delim = ($opt_C || '\s') . ($opt_w ? '+' : '*');
($rawdelim = $delim) =~ s/\W/\\$&/g;
$in  = join('|', (@in  = ('\033\$\@', '\033\$B')));
$out = join('|', (@out = ('\033\(J',  '\033\(B')));
$shiftcode   = '(' . join('|', @in, @out) . ')';
$optionalseq = '(' . join('|', length, @in, @out, $opt_C || '\s'). ')*';
($rawoptionalseq = $optionalseq) =~ s/\W/\\$&/g;
sub makepat {
    local($pat, $p) = @_;
    for (split(/$shiftcode/, $pat)) {
	if (/$in/o)  { $jis = 1; $p .= $optionalseq if $p; next; }
	if (/$out/o) { $jis = 0; next; }
	if ($jis)    { s/../&jis($&)/eg; $p .= $_; next; }
	s/([\200-\377])?./length($&) > 1 ? &mb($&) : &asc($&)/eg; $p .= $_;
    }
    $p =~ s/($rawdelim|$rawoptionalseq)+$//;
    length($p) ? $p : undef;
}
$opt_f && do { open(F, $opt_f) || die "$opt_f: $!\n"; chop($opt_f = <F>); };
defined $opt_p || defined($opt_p = $opt_f || shift) || &usage;
($opt_p, $opt_v) = (&makepat($opt_p), &makepat($opt_v));
($opt_P, $opt_V) = (&wildcard($opt_P), &wildcard($opt_V));
grep(eval "\$opt_$_=0,warn\"-$_ is disabled.\n\"if\$opt_$_;", 'q', 'u', 'b')
    if defined($jis);

($ql, $qr, $qd, $qe) = ('>>', '<<', '', '') if $opt_q;
($ql, $qr, $qd, $qe) = &sose if ($opt_Q && ($opt_Y || -t STDOUT));

($nlqsubs, $nlsubs) = $opt_n ? ('"$qd\n$fn".++$tl.":$qe"', '"\n$fn".++$tl.":"')
			     : ('"$qd\n$fn$qe"', '"\n$fn"');
($effect = $opt_b || $opt_u) && &initsubs;
$opt_O = $opt_o ? '\n\n' : '\n' unless defined($opt_O);
$opt_O =~ s/"/\\"/g;
eval "\$rs = \"$opt_O\"";	# record separator
grep(eval "print \"opt_$_=/\$opt_$_/\n\" if \$opt_$_;", split(//, 'pvPVCO'))
    if $opt_d;

$ig = 'i' if $opt_i;
$showfname = !$opt_h && (@ARGV > 1 || $opt_R || $opt_S);
$needinfo = $showfname || $opt_n;
$neednlsubs = !$opt_s && $needinfo;
$p_all = !($opt_m || $opt_M);
$binary = $opt_B;

($pre_c, $post_c) = /,/ ? split(',') : ($_, $_) if defined($_ = $opt_c);
$pre_c = $post_c = 1 if $binary;
$pre_c = $opt_o ? -1 : 1 unless defined($pre_c);
$post_c = $opt_o ? -1 : 1 unless defined($post_c);

$* = 1;
push(@ARGV, '-') if @ARGV == 0;
while (defined($file = $opt_S ? <> : shift)) {
    chop($file) if $opt_S;
    if (-d $file) {
	unshift(@ARGV, &getdirent($file)) if $opt_R;
	next;
    }
    next if $opt_T && ($binary = -B $file) && !$opt_B;
    open(F, $file) || do { $error = 2; warn "$file: $!\n" if !$opt_I; next; };
    open(F, '-|') || exec('zcat', $file) || die("zcat: $!\n")
	if ($file =~ /\.Z$/ && !$opt_z);
    undef $/; $_ = <F>; $/ = "\n"; close(F);
    print $file, $opt_T && $binary ? ' (binary)' : '', ":\n" if $opt_x;
    if ($opt_l) {eval 'print("$file\\n"),$matched++ if /'."$opt_p/$ig"; next;}
    $#x = $[ - 1;
if ($g_option_works) {	# 4.019 is not enough good
    eval "while(/$opt_p/og$ig){push(\@x,length(\$`),length(\$&));}";
} elsif (($test || (($test = '10') =~ s/0/$`/, $test)) eq '11') {
    eval 's/'.$opt_p.'/push(@x,length($`),length($&));$&/eg'.$ig;
} else {		# buggy case
    $m = length;
    eval 's/$opt_p/$t=length($&);push(@x,'.$m.'-length($\')-$t,$t);$&/ego'.$ig;
}
    $fn = "$file:" if $showfname;
    if ($opt_a) {
	for ($op = 0; ($p, $len) = splice(@x, 0, 2); $op = $p + $len) {
	    $matched++;
	    $match = substr($_, $p, $len);
	    $match = &effect($match) if $effect;
	    print substr($_, $op, $p - $op), $ql, $match, $qr;
	}
	print substr($_, $op);
	next;
    }
    for ($line = 1, $op = 0; ($p, $len) = splice(@x, 0, 2); ) {
	$print = $p_all;
	@out = ($fn);
	$line += (substr($_, $op, $p - $op) =~ tr/\n/\n/) if $opt_n || $opt_g;
	if ($opt_g) {
	    $pre_c = ($line - 1) % $opt_g + 1;
	    $post_c = $opt_g - $pre_c + 1;
	}
	$op = $pnl = $p;
	for ($n = $pre_c; ($opt_o || $n) && ($pnl >= 0); $n--) {
	    $pnl = rindex($_, "\n", $pnl - 1);
	    last if ($opt_o && (index($_, $rs, $pnl) == $pnl));
	    push(@out, "[...\n"), last if ($opt_o && ($n == 1));
	}
	$left = substr($_, $pnl + 1, $p - $pnl - 1);
	push(@out, $opt_s ? $line : ($tl = $line - ($left =~ tr/\n/\n/)), ':')
	    if $opt_n;
	push(@out, $p, ':') if $opt_N;
	$left =~ s/\n/$nlsubs/gee if $neednlsubs;
	$left =~ s/.*[^\b\s!-~]// if $binary;
	push(@out, "\n") if ($opt_s && $needinfo);
	push(@out, $left);
	for (;; ($p, $len) = splice(@x, 0, 2)) {
	    @cont = ();
	    $match = substr($_, $p, $len);
	    $print += (index($match, "\n") >= $[) if $opt_m;
	    $match = &effect($match) if $effect;
	    $match =~ s/\n/$nlqsubs/gee if $neednlsubs;
	    $post_c -= ($match =~ tr/\n/\n/) if $opt_g;
	    push(@out, $ql, $match, $qr);
	    $nnl = ($p += $len) - 1;
	    for ($n = $post_c; $n || $opt_o; $n--, $nnl = $tnnl) {
		last if ($tnnl = index($_, "\n", $nnl + 1)) < 0;
		last if ($opt_o && (index($_, $rs, $nnl = $tnnl) == $nnl));
		@cont = ("...]\n"), last if ($opt_o && $n == 1);
	    }
	    last if ($nnl < $x[$[] || $opt_2 || @x < 2);
	    $opt_M && $print++;
	    $between = substr($_, $p, $x[$[] - $p);
	    last if $binary && $between =~ /[^\b\s!-~]/;
	    $between =~ s/\n/$nlsubs/gee if $neednlsubs;
	    $post_c -= ($between =~ tr/\n/\n/) if $opt_g;
	    push(@out, $between);
	}
	$right = substr($_, $p, $nnl - $p);
	next if ($opt_v ne '' && substr($_, $pnl, $nnl - $pnl) =~ /$opt_v/o);
	$right =~ s/[^\b\s!-~].*// if $binary;
	$right =~ s/\n/$nlsubs/gee if $neednlsubs;
	push(@out, $right, "\n", @cont);
	unshift(@out, "\f\n") if ($opt_L && $matched);
	print @out if ($print && ++$matched);
    }
}
exit($error || !$matched);
######################################################################
sub asc {
    local($_) = @_;
    $opt_E || s/\s/$delim/ || $opt_e || s/\W/\\$&/, $_;
}
sub mb {
    local($_, @_) = ($_[$[], split(//, shift));
    $_ = sprintf("\\%03o\\%03o", ord(shift), ord(shift)) if @_ == 2;
    $opt_E ? $_ : $_.$delim;
}
sub jis {
    $_[$[] =~ s/(\W)/\\$1/g;
    $_[$[] . $optionalseq;
}
sub initsubs {
    @ul[1,2] = ("_\010", "__\010\010"); @bs[1,2] = ("\010", "\010\010");
    $s  = 'sub effect{$_[$[]=~s/[\\200-\\337].|./$l=length($&);';
    $s .= '$ul[$l].' x $opt_u . '$&.$bs[$l].' x $opt_b . "\$&/ge;shift;}\n";
    eval $s; print $s if $opt_d && ($opt_u || $opt_b);
}
sub getdirent {
    local($dir, $_, @ent) = @_;
    print "Entering \"$dir\".\n" if $opt_d;
    return @ent if (-l $dir && !$opt_F);
    opendir(DIR, $dir) || do { warn "$dir: $!\n"; return @ent; };
    push(@ent, $_) while ($_ = readdir(DIR));
    close(DIR);
    @ent = grep(!m#^\.\.?$# && (-d "$dir/$_" || $opt_P eq '' || m/$opt_P/o)
		&& ($opt_V eq '' || !m/$opt_V/o) && s#^#$dir/#, sort @ent);
}
sub wildcard {
    local($_) = @_;
    s#\\?.#$_ = $&; s/\\?([_0-9A-Za-z])/$1/ || /\\./ || s/[*]/.*/ ||
	s/[|]/\$|^/ || tr/?{,}[]\-/.(|)[]\-/ || s/./\\$&/; $_;#ge;
    length($_) ? "^$_\$" : undef;
}
sub sose {
    do 'ioctl.ph' || do 'sys/ioctl.ph';
    require('termcap.pl'); $ospeed = 1 unless $ospeed;
    &Tgetent; $so = &Tputs($TC{'so'}); $se = &Tputs($TC{'se'});
    ($so, $se, $se, $so);
}
######################################################################
;#------------------------------------------------------------
;# usage.pl: make a string for usage line.
;#	by K. Utashiro <[email-masked]> on Sep 7 1990
;#	Revised by utashiro on Mar 16 1991
;#	Revised by utashiro on Mar 20 1991
;#
;# Syntax: &Usage($command, $option, $trailer, @arglist);
;#	$command: command name (maybe $0)
;#	$option:  option string same as &Getopt
;#	$trailer: trailer string (optional)
;#	@arglist: description for options which takes argument (optional)
;#		  format is "option character : argument : description"
;#		  where argument and description are optional.
;#		  special form '-:xyz' hides options -x, -y, -z.
;#
;# &Usage returns list of two strings where 1st string is for usage
;# line and 2nd is for description.
;#
;# Example:
;#	$opts = 'deg:u:s:x'; @arglist = (
;#		'-:x',			# means -x is secret option
;#		'd::debug',
;#		'g:group',
;#		'u:user:user name',
;#	);
;#	unless (&Getopts($opts)) {
;#		print &Usage($0, $opts, 'file ...', @arglist);
;#		exit(1);
;#	}
;#
;# Result:
;#	usage: sample [ -d ] [ -e ] [ -g group ] [ -u user ] [ -s : ] file ...
;#		-d       debug
;#		-u user  user name
;#
sub Usage {
    package usage; reset('a-z');
    local($cmd, $opt, $trailer, @arglist) = @_;
    for (@arglist) {
	($name, $arg, $desc) = split(/:/, $_, 3);
	$arg =~ s/\|.*//;
	if ($name eq '-') {
	    grep($hide{$_}++, split('', $arg)); next;
	}
	next if $hide{$name};
	$arg{$name} = $arg;
	$desc{$name} = $desc;
	$w = length($arg) if ($desc && $w < length($arg));
    }
    $cmd =~ s#.*/##;
    push(@usage, 'usage:', $cmd);
    while ($opt =~ /^\s*(.)(:?)/) {
	$opt = $';
	next if $hide{$1};
	push(@opts, $1);
	push(@usage, '[', "-$1");
	push(@usage, $arg{$1} || $2) if $2;
	push(@usage, ']');
    }
    push(@usage, $trailer) if $trailer;
    for (grep($desc{$_}, @opts)) {
	push(@desc, sprintf("\t-%s %-${w}s  %s\n", $_, $arg{$_}, $desc{$_}));
    }
    (join(' ', @usage)."\n", join('', @desc));
}
1;
######################################################################
.00;			# finish .ig
 
'di			\" finish diversion--previous line must be blank
.nr nl 0-1		\" fake up transition to first page again
.nr % 0			\" start at page 1
';<<'.ex'; #__END__ ############# From here on it's a standard manual page #
.TH MG 1 "Jul 11, 1991"
.AT 3
.SH NAME
mg \- multi-line grep
.SH SYNOPSIS
.B mg
[
.B options
]
.I pattern
[
.I file
\&... ]
.SH DESCRIPTION
.I Mg
searches the specified pattern from files or standard input
and print lines which contain the pattern.  It has almost
same function as Unix command
.IR grep (1)
but is distinguished from grep because the matching is done
across the line boundaries.
.PP
For example, to find a sentence ``internet control message
protocol'' from many RFC texts, you can say
.nf

	mg\ \-i 'internet control message protocol'\ *.txt

.fi
Match will occur for sequence of words `internet',
`control', `message', `protocol' separated by any number of
whitespace characters including null string (\-w option
avoids null matching).
.PP
.I Mg
is also useful to find a word from Japanese text because
Japanese words are not separated by whitespaces, and newline
character can be inserted at any place of the text.  As a
matter of fact,
.I mg
is made for Japanese string search originally.  Any Japanese
codes including JIS, Shift-JIS, EUC can be handled
hopefully, but JIS code disables some features and may make
the command confused when searching a short string.
.PP
If the file has .Z suffix, it is uncompressed before search.
.SH ENVIRONMENT
Environment variable MGOPTS is used as a default options.
.SH OPTIONS
.LP
GREP COMPATIBLE OPTIONS:
.RS
.IP \-i
Ignore case.
.IP \-l
List filename only.
.IP \-n
Show line number.
.IP \-h 
Do not display filenames even if multiple filenames are
specified by command line.
.RE
.LP
SLIGHTLY DIFFERENT OPTIONS:
.RS
.IP \-w 
Word sensitive.  Space character in the pattern matches null
string by default.  So pattern ``a\ b'' matches to string
``ab''.  With this option, space character matches single or
more space.
.IP "\-v \fIpattern\fP"
Skip the line if matched with pattern.  Don't print the
matched line if it matched to the pattern specified with
this option.  This option doesn't have any effect used with
\-a or \-l option.
.RE
.LP
OTHER OPTIONS:
.RS
.IP \-N
Print byte offset of matched string.  If multiple matching
is occured in one line, only first matching offset is
printed.  Use \-2 option to avoid it.
.IP \-e 
Use the pattern as a regular expression in 
.IR perl (1)
but space is treated specially.  With this option, you can
use
.I mg
like
.IR egrep (1)
like this:
.nf

	mg \-e 'foo bar|\^goo car|\^hoo dar' ...

.fi
See
.IR perl (1)
for detail of regular expression.
.IP
Note that if you are running
.IR jperl (1)
kanji code can be used in range expression, but you have to
use \-E option to do that.
.IP \-E 
Use the pattern as regular expression in
.I perl
completely.
.IP "\-c \fIn[,n]\fP"
Print n-lines before/after matched line.  Default n is 1,
which means only one line is displayed.  N is number of
newlines surrounding matched pattern.  If ``\-c\ 3''
options is suplied, two lines before and after matched
line will be displayed together.  You can see only after
two lines by ``\-c 1,3'' option.
.IP
Option \-c0 displays matched string only.  Next example is
almost equivalent to
.IR strings (1)
command with \-o option.
.nf

	mg \-Nec0 '[\es\e040-\e176]{5,}' file

.fi
.IP "\-o"
Print the paragraph which contains the pattern.  Each
paragraph is delimited by two successive newline character
by default.  Be aware that emply line is not paragraph
delimiter if which contains space characters.  Example:
.nf

	mg \-nQo 'setuid script' /usr/man/catl/perl.l

	mg \-o sockaddr /usr/include/sys/socket.h

.fi
If \-c option is also supplied and there are more lines in
the paragraph, continuous mark is displayed.
.IP "\-O \fIstring\fP"
Specify paragraph delimiter string as well as activate the
paragraph mode.  The contents of string is evaluated as is
inside double-quote not as a regular expression.  For
example, you can get lines between troff macros like this:
.nf

	mg \-QO "\en." 'setuid script' /usr/man/manl/perl.l

.fi
.IP "\-g \fIlines\fP"
Page mode.  Provided number of lines for each pages, pages
which contains pattern will be displayed.  For example, you
can get pages which contain some strings from nroff'ed text
like this:
.nf

	mg \-Q \-g 66 'setuid script' /usr/man/catl/perl.l

.fi
You can't use \-c with this option.  Formfeed is not
supported currently.
.IP "\-C \fIchars\fP"
Continuous character.  If you want search sentence continued
by other than white space characters, continuous characters
can be set by this options.  For example, next command
find a sentence even if it is quoted by `>' or `|' mark.
.nf

	mg \-C '>\^|\^' 'ninja shogun fujiyama' `mhpath all`

.fi
To search a pattern in C style comment:
.nf

	mg \-C '/*' 'setuid scripts' perl.c

.fi
.IP
Note that continuous characters don't have to be found only
top of the string.  So ``foo\ bar'' matches a string
``foo>>bar'' on the previous example.
.IP \-u 
Underline matched string.  Makes a matched string underlined
by precede each character by ``_^H''.
.IP \-b 
Make bold matched string.  Makes a matched string
overstriked like ``f^Hfo^Hoo^Ho''.
.IP \-q 
Quote matched string by like ``>>matched<<''.  This options
is disabled when searching JIS file.
.IP \-Q 
Use a stand-out feature of the terminal to quote the matched
string (not for JIS).  This options is ignored when the
standard output is not a terminal.  \-q and \-Q are useful
for long line.  Try
.nf

	echo $path | mg \-Q mh

.fi
.IP \-a 
Print all contents of the file.  This option makes a sense
only if used with options like \-q, \-Q, \-u, \-b, otherwise
behave almost same as 
.IR cat (1).
Filename and lines are not printed with this option.
.IP \-s 
When multiple files are specified, each matched line are
preceded by ``filename:'' string.  With this option, newline
character is inserted between filename and matched line.
This option is useful when the filenames are very long.
.IP \-2 
Usually only one line is displayed even if multiple matching
is occurred for the same line.  With this option, each
matching will be displated in different line.
.IP \-R 
Search recursively.  Only files specified by command line
arguments are searched by default.  When invoked with this
option and arguments contains a directory, it is searched
recursively.  Usually used with \-P or \-T option.
.IP "\-P \fIpattern\fP"
Search file pattern.  When directories are searched
recursively, only files which matches the `pattern' is
searched.  A `pattern' is specified in wildcard format same
as shell and `|\^' character can be used for alternative in
addition.  For example, you can find a string ``foobar''
>from all C source files and makefiles like this:
.nf

	mg \-RP '*.c|\^[Mm]akefile' foobar /usr/src

.fi
.IP "\-V \fIpattern\fP"
Exception file pattern.  This is a counterpart of \-P.  Only
files which DOES NOT match the pattern will be searched.
.nf

	mg \-RV '*.[oas]' foobar /usr/src

.fi
.IP
Note that \-V option is also applied to a directory name
while \-P option has an effect only for a file.  This means
you can specify a directory name to skip, but can't specify
a directory name to search.
.IP \-F
Follow symbolic link of a directory.  Doesn't follow by
default.
.IP \-T 
Search text file only.  Binary file is skiped with this
option.  Decision is made by perl operator \-T.  See \-B
option.
.IP \-B
Find string from binary file.  Only printable characters
surrounding matched pattern are printed.  If both \-T and
\-B are supplied, text file is searched in normal mode and
binary file is searched in binary mode.  Next example is
almost same as
.IR what (1).
.nf

	mg \-B '@(#)' /bin/awk

.fi
.IP \-L
Print formfeed between each matchings.  Print the formfeed
character before each matched line.  This options is useful
used with \-c option and piped to pager command.
.IP \-S 
Get filenames from standard input.  Read standard input and
use each line as a filename for searching.  You can feed the
output from other command like
.IR find (1)
for
.I mg
with this option.
.IP \-m 
Print matched line only when the pattern is across the line.
.IP \-M 
Print matched line only when multiple matching is occurred
for the same line.
.IP "\-f \fIfile\fP"
Specify the file which contains search pattern.  Only the
first line of the file is used.  This options is useful when
input of KANJI character is difficult from tty driver.
.IP \-p pattern
Specify search pattern.  You don't have to use this option
explicitly because the first argument after options will be
treated as a pattern.
.IP \-x 
Print processing filename.
.IP \-z 
Disables automatic uncompress.
.RE
.SH APPENDIX
You might want to use
.IR mg (1)
instead of
.IR grep (1)
>from GNU emacs.  In that case please add following program
in your .emacs file.
.ne 8
.nf

	(defun mg (command)
	  "Run mg instead of grep."
	  (interactive "sRun mg (with args): ")
	  (require 'compile)
	  (compile1 (concat "mg -n " command " /dev/null")
		    "No more mg hits" "mg"))

.fi
You have to visit uninterested line when sorrounding lines
are displayed by \-c or \-o option.  Use \-s option to avoid
this.
.SH AUTHOR
Kazumasa Utashiro <[email-masked]>
.br
Software Research Associates, Inc., Japan
.SH "SEE ALSO"
grep(1), perl(1), jperl(1)
.SH BUGS
.PP
Hypheneation is not supported.  Please don't ask me to
support skipping header and footer inserted by nroff...
.PP
Long JIS code pattern can not be processed.
.ex