36 Fixing grep


#36 Fixing grep

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. This script also borrows from the ANSI color script, Script #11.

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"   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   uniq  more   fi } trap "/bin/rm -f $tempout $sedscript" EXIT if [ -z "" ] ; then   echo "Usage: 
 #!/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 $1cut -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 
[-c X] pattern {filename}" >&2; exit 0 fi if [ "" = "-c" ] ; then context="" shift; shift elif [ "$(echo cut -c1-2)" = "-c" ] ; then context="$(echo cut -c3-)" shift fi pattern=""; 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.




Wicked Cool Shell Scripts. 101 Scripts for Linux, Mac OS X, and Unix Systems
Wicked Cool Shell Scripts
ISBN: 1593270127
EAN: 2147483647
Year: 2004
Pages: 150
Authors: Dave Taylor

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net