context-grep
Leo de Wit
leo at philmds.UUCP
Sat Feb 11 23:49:52 AEST 1989
In article <2017 at piraat.cs.vu.nl> maart at cs.vu.nl (Maarten Litmaath) writes:
|How about `sed'? I think Leo de Wit [a.k.a. Mr. Sed] will have some remarks
|about `cgrep', but it's a start.
Ah, you asked for it!
I looked at Maarten's script and modified some of it. The result is
appended below. Modifications:
1) Changed use of [ by case whenever possible, 'cause this is a builtin.
2) Changed while-test-expr loops to construct a repeated pattern ($before
and $after) by a yes|sed construct. Neat trick, if I may say so myself (8-).
3) Changed the sed expression, since it didn't handle well an appearance
of $pattern in the 'after pattern part' (was treated as an ordinary line).
4) Prepend each line output by <filename>:, this is perhaps more in the
style of grep. It also obviates the need of a temporary file. This however
is clearly a matter of taste.
Ad 2): if your system doesn't support yes (a never ending echo), you can
build it easily from echo and sed:
echo $*|sed '
: again
p
b again'
yes and sed also make for an easy range generator (this was also in this
newsgroup, where someone wanted to create ranges without using a C program)
($1 and $2 are respectively the first and last number to be generated):
yes|sed -n "$1,$2{;=;$2q;}"
Leo.
P.S. The modified cgrep follows here:
-------------------------------
#! /bin/sh
# cgrep - context grep
#
# grep pattern plus surrounding lines
# @(#)cgrep 1.1 89/01/18 Maarten Litmaath
# modified 89/02/11 Leo de Wit
#
# example: "cgrep -5 +0 '^{' *.c" shows all function headers in the C sources,
# with (max.) 5 lines preceding the `{', followed by 0 lines (no line will be
# printed twice; there might not be as many contextual lines as requested)
# each line is prepended with the filename it appears in, followed by a colon.
# cgrep can be used as a filter; the file name will be `STDIN'
# the `--' option can be used to `protect' a pattern starting with `-'
usage="Usage: cgrep [-<# before>] [+<# after>] [--] <regexp> [<files>]"
case $# in 0) echo "$usage"; exit 1;; esac
b=2 a=2
while :
do
case $1 in
--)
shift
break
;;
-*)
b=`echo "x$1" | sed s/..//`
shift
;;
+*)
a=`echo "x$1" | sed s/..//`
shift
;;
*)
break
esac
done
case $# in 0) echo "$usage"; exit 1;; esac
pattern=`echo "$1" | sed 's-/-\\\/-'`
shift
case $b in "") b=1;; esac
case $a in "") a=1;; esac
case $b in
0) branch=b;;
*)
case "$pattern" in
\^*)
pattern=`echo "$pattern" | sed 's/./\\\n/'`
esac
before=`yes "\n[^\n]*"|sed -n "
: back
$b{
s/\n//g
p
q
}
N
b back"`;;
esac
case $a in
0) after= ;;
*) after=`yes "\n[^\n]*"|sed -n "
: back
$a{
s/\n//g
p
q
}
N
b back"`;;
esac
case $# in
0) files=STDIN
set dummy;;
*) files="$*"
set dummy $*;;
esac
umask 077
for i in $files
do
shift
# The hold space will hold (at most) b lines (if not in the pattern part)
# CLRHLD (Clear hold space) and ADJUST (trim number of lines in hold space)
# are 'in hold space context', NEXT is 'in pattern space context'.
sed -n "/$pattern/{
x
/^\n/{
s/^\n/$i:/
s/\n/&$i:/g
p
}
x
: CLRHLD
x
s/.*//
: NEXT
x
s/^/$i:/p
n
/$pattern/b CLRHLD
H
x
/\n[^\n]*$after/!b NEXT
a\\
-----
b ADJUST
}
H
x
: ADJUST
s/.*\($before\)/\1/
x
" $1
done
-------------- ends here -------------
More information about the Comp.unix.questions
mailing list