shell相关:指令篇 基础篇 脚本欣赏 编程实例 shell问问 shell视频教程 技巧篇 水平测试 E文资料 vi编辑器 高级Bash脚本编程指南
其他:mysql perl c语言
Some versions of grep offer a remarkable variety of capabilities, including the particularly useful ability to show the context (a line or two above and below) of a matching line in the file. Additionally, some rare versions of grep can highlight the region in the line (for simple patterns, at least) that matches the specified pattern.
Both of these useful features can be emulated in a shell script, so that even users on older commercial Unixes with relatively primitive grep commands can enjoy them.
The Code
#!/bin/sh
# cgrep - grep with context display and highlighted pattern matches.
context=0
esc="^["
bOn="${esc}[1m" bOff="${esc}[22m"
sedscript="/tmp/cgrep.sed.$$"
tempout="/tmp/cgrep.$$"
function showMatches
{
matches=0
echo "s/$pattern/${bOn}$pattern${bOff}/g" > $sedscript
for lineno in $(grep -n "$pattern" $1 | cut -d: -f1)
do
if [ $context -gt 0 ] ; then
prev="$(($lineno - $context))"
if [ "$(echo $prev | cut -c1)" = "-" ] ; then
prev="0"
fi
next="$(($lineno + $context))"
if [ $matches -gt 0 ] ; then
echo "${prev}i\\" >> $sedscript
echo "----" >> $sedscript
fi
echo "${prev},${next}p" >> $sedscript
else
echo "${lineno}p" >> $sedscript
fi
matches="$(($matches + 1))"
done
if [ $matches -gt 0 ] ; then
sed -n -f $sedscript $1 | uniq | more
fi
}
trap "/bin/rm -f $tempout $sedscript" EXIT
if [ -z "$1" ] ; then
echo "Usage: $0 [-c X] pattern {filename}" >&2; exit 0
fi
if [ "$1" = "-c" ] ; then
context="$2"
shift; shift
elif [ "$(echo $1|cut -c1-2)" = "-c" ] ; then
context="$(echo $1 | cut -c3-)"
shift
fi
pattern="$1"; shift
if [ $# -gt 0 ] ; then
for filename ; do
echo "----- $filename -----"
showMatches $filename
done
else
cat - > $tempout # save stream to a temp file
showMatches $tempout
fi
exit 0
How It Works
This script uses grep -n to get the line numbers of all matching lines in the file and then, using the specified number of lines of context to include, identifies a starting and ending line for displaying each match. These are written out to the temporary sed script, along with a word substitution command (the very first echo statement in the showMatches function) that wraps the specified pattern in bold-on and bold-off ANSI sequences. That's 90 percent of the script, in a nutshell.
Running the Script
This script works either with an input stream (in which case it saves the input to a temp file and then processes the temp file as if its name had been specified on the command line) or with a list of one or more files on the command line. To specify the number of lines of context both above and below the line matching the pattern that you specified, use -c value, followed by the pattern to match.
The Results
$ cgrep -c 1 teacup ragged.txt
----- ragged.txt -----
in the wind, and the pool rippling to the waving of the reeds--the
rattling teacups would change to tinkling sheep-bells, and the
Queen's shrill cries to the voice of the shepherd boy--and the
Hacking the Script
A useful refinement to this script would return line numbers along with the matched lines.