#!/bin/sh prog=`basename $0` use() { cat </dev/null | awk '$2 != "not" {print $NF}' } AWK=`findcommand mawk` if [ "$AWK" = "" ] ; then AWK=`findcommand gawk` ; fi if [ "$AWK" = "" ] ; then AWK=`findcommand nawk` ; fi if [ "$AWK" = "" ] ; then AWK=`findcommand awk` ; fi # getopt loses quotes around whitespace, so we won't use it. debug=no underscore_style=none enter_hl=smso exit_hl=rmso delete_lines=no ### word_left= ### word_right= while [ $# -gt 0 ] ; do case "$1" in -h ) use ; exit 0 ;; -D ) debug=yes ; shift ;; -e ) break ;; # reached a sed expression -d ) delete_lines=yes ; shift ;; -b ) enter_hl=bold ; exit_hl=rmso ; shift ;; -r ) enter_hl=rev ; exit_hl=rmso ; shift ;; -u ) enter_hl=smul ; exit_hl=rmul ; shift ;; -B ) underscore=backspace ; shift ;; -o ) underscore=overstrike ; shift ;; ### -w ) word_left='[^_a-zA-Z]' ; word_right='[^_a-zA-Z0-9]' ; shift ;; -- ) shift ; break ;; -* ) echo "Unknown option \`$1'" ; exit 1 ;; * ) break ;; esac done X=`tput $enter_hl` Y=`tput $exit_hl` test "$X" = "" -o "$Y" = "" && { X=`tput smso` ; Y=`tput rmso` ; } # Build up the appropriate sed args and append them to the command line, # so as to take advantage of the quote-preserving done with "$@". if [ $# -gt 0 ] ; then test "$1" = "-e" && shift # Set up to work w/ or w/o initial -e. have_e=yes nargs=$# done_w_pats=no while [ $nargs -gt 0 ] ; do word=$1 ; shift ; nargs=`expr $nargs - 1` ### echo "word is $word" ### echo "arglist is $@" anchor_l= anchor_r= # special-case leading ^, trailing $ case "$word" in "^"* ) word=`expr "$word" : '.\(.*\)'` ; anchor_l="^" ;; esac case "$word" in *\\$ ) ;; *$ ) word=`expr "$word" : '\(.*\).'` ; anchor_r="$" ;; esac # If done with all patterns (only have filenames left), append filename # to end of arg list being built and continue. case "$done_w_pats" in yes ) set -- ${1+"$@"} "$word" ; continue ;; esac # Not done with options and pattern processing... case "$have_e,$word" in no,-e ) # This is the "-e" that introduces a pattern as the next arg. have_e=yes continue ;; no,* ) # Previous word wasn't -e, and this word isn't -e, either. # Therefore it must be a filename. done_w_pats=yes # Append filename to the arglist, but first check if we must # add the sed code for deleting unmatched lines. case $delete_lines in yes ) set -- ${1+"$@"} -e t -e d "$word" # Turn off the delete_lines flag so we don't # add that sed code again: delete_lines=no ;; no ) set -- ${1+"$@"} "$word" ;; esac ;; yes,* ) # Previous word was -e; this word must be a pattern. have_e=no pat=`echo "$word" | sed 's/\//\\\/'` set -- ${1+"$@"} -e \ "s/$anchor_l\($pat\)$anchor_r/$X\1$Y/g" ### Word selection doesn't work because the following ### regexp won't match at beginning or end of line. ### set -- ${1+"$@"} -e \ ### "s/$anchor_l\($word_left\)\($pat\)\($word_right\)$anchor_r/\1$X\2$Y\3/g" ;; esac done # Now check if $delete_lines is still pending: case $delete_lines in yes ) set -- ${1+"$@"} -e t -e d ;; esac fi test "$debug" = yes && echo " # sed " ${1+"$@"} case "$underscore" in overstrike ) sed ${1+"$@"} | $AWK ' NR == 1 { lX = length(X) ; lY = length(Y) } { iY = 3000 while ( (iX=index($0, X)) > 0 ) { if ((iY = index($0, Y)) == 0) iY = length($0) + 1 printf("%s", substr($0, 1, iX-1)) for (i = iX+lX; i < iY; i++) printf("%s\b%s", substr($0, i, 1), substr($0, i, 1)) $0 = substr($0, iY+lY, 3000) } print $0 }' X="$X" Y="$Y" - ;; backspace ) sed ${1+"$@"} | $AWK ' NR == 1 { lX = length(X) ; lY = length(Y) } { iY = 3000 while ( (iX=index($0, X)) > 0 ) { if ((iY = index($0, Y)) == 0) iY = length($0) + 1 printf("%s", substr($0, 1, iX-1)) for (i = iX+lX; i < iY; i++) printf("_\b%s", substr($0, i, 1)) $0 = substr($0, iY+lY, 3000) } print $0 }' X="$X" Y="$Y" - ;; * ) sed ${1+"$@"} ;; esac