#!/bin/bash # I originally intended this to work with bourne shells, but then I # discovered that Solaris' /bin/sh -still- doesn't understand shell # functions. Grrr... So because RHEL 3, Solaris 7, IRIX 6.5.x and # Tru64 4.x all have /bin/ksh, I'm switching to that. #set -x # this is definitely not the most efficient language choice for this # project, but: # 1) All of our autoinstall systems have /bin/sh present during an # install # 2) We're not using any external programs during the main loop, so it # may not actually be all -that- slow anyway # Deter/prevent an extra degree of whitespace munging IFS="" export IFS function usage { ( echo echo "$0: usage follows" echo " -p pattern specify the shell pattern, before or after which the text will be added" echo " -a perform operation after the pattern" echo " -b perform operation before the pattern" echo " -i perform an insert" echo " -r perform a removal (not yet implemented)" echo " -t text the text to add" echo " -f add text only before/after the -first- occurrence of the pattern" echo " -F filename file to operate on. Default is to read from stdin and write to stdout" echo " -d output some debugging information" echo echo "You must always specify both -p and -t" echo "You must always specify either -a or -b but not both" echo "You must always specify either -i or -r but not both" ) 1>&2 exit 1 } function premature_eof { echo "$0: Warning: EOF detected prior to pattern, stream unchanged" 1>&2 } # getopt seems to make a general mess of quoting, so we do our own # options parsing... #set -- `getopt p:abirt: $@` #if [ $? != 0 ] #then # usage #fi pattern="" after="" text="" insert="" remove="" first="false" debug="false" filename="" while [ "$#" -ge 1 ] do : '$1' is $1, '$2' is $2 case "$1" in -p) if [ "$pattern" != "" ] then echo -p must be specified exactly once usage fi pattern="$2" shift shift ;; -F) if [ "$filename" != "" ] then echo -F must be zero or one times, not more usage fi filename="$2" shift shift ;; -f) if [ "$first" != "false" ] then echo -f may only be specified once 1>&2 usage fi first=true shift ;; -d) if [ "$debug" != "false" ] then echo -d may only be specified once 1>&2 usage fi debug=true shift ;; -a) if [ "$after" != "" ] then echo -a and -b are mutually exclusiva 1>&2 usage fi after=true shift ;; -b) if [ "$after" != "" ] then echo -a and -b are mutually exclusiva 1>&2 usage fi after=false shift ;; -t) if [ "$text" != "" ] then echo -t must be specified exactly once usage fi text="$2" shift shift ;; -i) if [ "$insert" != "" ] then echo -i may only be specified once 1>&2 usage fi if [ "$remove" != "" ] then echo -i and -r are mutually exclusive 1>&2 usage fi insert="true" shift ;; -r) if [ "$remove" != "" ] then echo -r may only be specified once 1>&2 usage fi if [ "$insert" != "" ] then echo -i and -r are mutually exclusive 1>&2 usage fi remove="true" shift ;; *) usage ;; esac done if [ "$pattern" = "" ] then echo -p must be specified exactly once 1>&2 usage fi if [ "$text" = "" ] then echo -t must be specified exactly once 1>&2 usage fi if [ "$insert" = "" ] && [ "$remove" = "" ] then echo You must specify one of -i or -r 1>&2 usage fi if [ "$after" = "" ] then echo You must specify one of -a or -b 1>&2 usage fi if [ "$filename" = "" ] then : 'nothing to do' else # create a temporary file, with who-cares-what-permissions cp "$filename" "$filename.temp" # our output will go back into the original file, with the same # permissions as before, by virtue of the > exec > "$filename" # we'll read datfa from the temporary file exec < "$filename.temp" fi if [ "$insert" = true ] then # insert case found=false if [ "$after" = true ] then # this is the simpler of the two insert cases. In this one, we add "$text" # after the pattern occurrence(s) while : do if read line then case "$line" in $pattern) found=true echo "$line" echo "$text" if [ "$first" = true ] then [ "$debug" = true ] && echo Setting cattoend cattoend=true break fi ;; *) echo "$line" ;; esac else : 'we are at EOF, so we do not need to cattoend' break fi if [ "$cattoend" = true ] then break fi done else # this is the more complicated of the two insert cases. In this one, we add "$text" # before the pattern occurrence(s) if read prevline then : else # if we did not even get one line, then just give the premature EOF warning and exit premature_eof exit 0 fi while : do if read line then eof=false else eof=true fi case "$prevline" in $pattern) found=true echo "$text" echo "$prevline" if [ "$eof" = true ] then break else if [ "$first" = true ] then echo "$line" [ "$debug" = true ] && echo Setting cattoend cattoend=true break fi fi ;; *) echo "$prevline" ;; esac if [ "$cattoend" = true ] then break fi if [ "$eof" = true ] then break fi prevline="$line" done fi fi [ "$debug" = true ] && echo '$found' is "$found" if [ "$found" = false ] then premature_eof fi if [ "$remove" = true ] then echo 'Sorry, remove is not implemented yet :)' 1>&2 exit 0 fi [ "$debug" = true ] && echo At end, and cattoend is "$cattoend" if [ "$cattoend" = true ] then while read line do echo "$line" done fi # clean up the temporary file, if needed if [ "$filename" = "" ] then : 'nothing to do' else rm "$filename.temp" fi