2.2. Shell wrapper, self-executing script

A sed or awk script would normally be invoked from the command line by a sed -e 'commands' or awk 'commands'. Embedding such a script in a bash script permits calling it more simply, and makes it "reusable". This also enables combining the functionality of sed and awk, for example piping the output of a set of sed commands to awk. As a saved executable file, you can then repeatedly invoke it in its original form or modified, without the inconvenience of retyping it on the command line.


Example 2-3. shell wrapper

   1 #!/bin/bash
   2 
   3 # This is a simple script that removes blank lines from a file.
   4 # No argument checking.
   5 
   6 # Same as
   7 #    sed -e '/^$/d' filename
   8 # invoked from the command line.
   9 
  10 sed -e /^$/d "$1"
  11 # The '-e' means an "editing" command follows (optional here).
  12 # '^' is beginning of line,
  13 # '$' is end,
  14 # and 'd' is delete.
  15 # Quoting the command-line arg permits special chars in the filename.
  16 
  17 exit 0


Example 2-4. A slightly more complex shell wrapper

   1 #!/bin/bash
   2 
   3 # "subst", a script that substitutes one pattern for
   4 # another in a file,
   5 # i.e., "subst Smith Jones letter.txt".
   6 
   7 ARGS=3
   8 E_BADARGS=65   # Wrong number of arguments passed to script.
   9 
  10 if [ $# -ne "$ARGS" ]
  11 # Test number of arguments to script
  12 # (always a good idea).
  13 then
  14   echo "Usage: `basename $0` old-pattern new-pattern filename"
  15   exit $E_BADARGS
  16 fi
  17 
  18 old_pattern=$1
  19 new_pattern=$2
  20 
  21 if [ -f "$3" ]
  22 then
  23     file_name=$3
  24 else
  25     echo "File \"$3\" does not exist."
  26     exit $E_BADARGS
  27 fi
  28 
  29 # Here is where the heavy work gets done.
  30 sed -e "s/$old_pattern/$new_pattern/g" $file_name
  31 # 's' is, of course, the substitute command in sed,
  32 # and /pattern/ invokes address matching.
  33 # The "g", or global flag causes substitution for *every*
  34 # occurence of $old_pattern on each line, not just the first.
  35 # Read the literature on 'sed' for a more
  36 # in-depth explanation.
  37 
  38 exit 0
  39 # Successful invocation of the script returns 0.


Example 2-5. A shell wrapper around an awk script

   1 #!/bin/bash
   2 
   3 # Adds up a specified column (of numbers) in the target file.
   4 
   5 ARGS=2
   6 WRONGARGS=65
   7 
   8 if [ $# -ne "$ARGS" ]
   9 # Check for proper no. of command line args.
  10 then
  11    echo "Usage: `basename $0` filename column-number"
  12    exit $WRONGARGS
  13 fi
  14 
  15 filename=$1
  16 column_number=$2
  17 
  18 # Passing shell variables to the awk part of the script is a bit tricky.
  19 # See the awk documentation for more details.
  20 
  21 # A multi-line awk script is invoked by   awk ' ..... '
  22 
  23 
  24 # Begin awk script.
  25 # -----------------------------
  26 awk '
  27 
  28 { total += $'"${column_number}"'
  29 }
  30 END {
  31      print total
  32 }     
  33 
  34 ' "$filename"
  35 # -----------------------------
  36 # End awk script.
  37 
  38 
  39 #   It may not be safe to pass shell variables to an embedded awk script,
  40 #   so Stephane Chazelas proposes the following alternative:
  41 #   ---------------------------------------
  42 #   awk -v column_number="$column_number" '
  43 #   { total += $column_number
  44 #   }
  45 #   END {
  46 #       print total
  47 #   }' "$filename"
  48 #   ---------------------------------------
  49 
  50 
  51 exit 0

For those scripts needing a single do-it-all tool, a Swiss army knife, there is Perl. Perl combines the capabilities of sed and awk, and throws in a large subset of C, to boot. It is modular and contains support for everything ranging from object-oriented programming up to and including the kitchen sink. Short Perl scripts can be effectively embedded in shell scripts, and there may even be some substance to the claim that Perl can totally replace shell scripting (though the author of this document remains skeptical).


Example 2-6. Perl embedded in a bash script

   1 #!/bin/bash
   2 
   3 # Some shell commands may precede the Perl script.
   4 
   5 perl -e 'print "This is an embedded Perl script\n"'
   6 # Like sed and awk, Perl also uses the "-e" option.
   7 
   8 # Some shell commands may follow.
   9 
  10 exit 0

Exercise. Write a shell script that performs a simple task.