Back: Test
Forward: Pattern Matching
 
FastBack: Pattern Matching
Up: Sh Implementation
FastForward: Environment
Top: Autoconf, Automake, and Libtool
Contents: Table of Contents
Index: Index
About: About this document

22.2.7 $

When using shell variables in your portable scripts, you need to write them in a somewhat stylised fashion to maximise the number of shell implementations that will interpret your code as expected:

  • Convenient though it is, the POSIX `$(command parameters)' syntax for command substitution is not remotely portable. Despite it being more difficult to nest, you must use ``command parameters`' instead.

  • The most portable way to set a default value for a shell variable is:

     
    $ echo ${no_such_var-"default value"}
    default value
    

    If there is any whitespace in the default value, as there is here, you must be careful to quote the entire value, since some shells will raise an error:

     
    $ echo ${no_such_var-default value}
    sh: bad substitution
    

  • The unset command is not available in many of the degenerate Bourne shell implementations. Generally, it is not too difficult to get by without it, but following the logic that led to the shell script in (), it would be trivial to extend the test case for confirming a shell's suitability to include a check for unset. Although it has not been put to the test, the theory is that all the interesting machines in use today have some shell that supports unset.

  • Be religious about double quoting variable expansions. Using `"$foo"' will avoid trouble with unexpected spaces in filenames, and compression of all whitespace to a single space in unquoted variable expansions.

  • To avoid accidental interpretation of variable expansions as command options you can use the following technique:

     
    $ foo=-n
    $ echo $foo
    $ echo x"$foo" | sed -e 's/^x//'
    -n
    

  • If it is set, IFS splits words on whitespace by default. If you change it, be sure to put it back when you're done, or the shell may behave very strangely from that point. For example, when you need to examine each element of `$PATH' in turn:

     
    # The whitespace at the end of the following line is a space
    # followed by literal tab and newline characters.
    save_IFS="${IFS=
    }"; IFS=":"
    set dummy $PATH
    IFS="$save_IFS"
    shift
    

    Alternatively, you can take advantage of the fact that command substitutions occur in a separate subshell, and do not corrupt the environment of the calling shell:

     
    set dummy `IFS=:; echo $PATH`
    shift
    

    Strictly speaking, the `dummy' argument is required to stop the set command from interpreting the first word of the expanded backquote expression as a command option. Realistically, no one is going to have `-x', for example, as the first element of their `PATH' variable, so the `dummy' could be omitted -- as I did earlier in the script in ().

  • Some shells expand `$@' to the empty string, even when there are no actual parameters (`$#' is 0). If you need to replicate the parameters that were passed to the executing script, when feeding the script to a more suitable interpreter for example, you must use the following:

     
    ${1+"$@"}
    

    Similarly, although all known shells do correctly use `$@' as the default argument to a for command, you must write it like this:

     
    for arg
    do
      stuff
    done
    

    When you rely on implicit `$@' like this, it is important to write the do keyword on a separate line. Some degenerate shells can not parse the following:

     
    for arg; do
      stuff
    done
    


This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html