|
22.2.4 ()
There are still a great number of shells that, like Steve Bourne's
original implementation, do not have functions! So, strictly speaking,
you can't use shell functions in your scripts. Luckily, in this day and
age, even though `/bin/sh' itself may not support shell functions,
it is not too far from the truth to say that almost every machine will
have some shell that does.
Taking this assumption to its logical conclusion, it is a simple matter
of writing your script to find a suitable shell, and then feed itself to
that shell so that the rest of the script can use functions with
impunity:
|
#! /bin/sh
# Zsh is not Bourne compatible without the following:
if test -n "$ZSH_VERSION"; then
emulate sh
NULLCMD=:
fi
# Bash is not POSIX compliant without the following:
test -n "$BASH_VERSION" && set -o posix
SHELL="${SHELL-/bin/sh}"
if test x"$1" = x--re-executed; then
# Functional shell was found. Remove option and continue
shift
elif "$SHELL" -c 'foo () { exit 0; }; foo' 2>/dev/null; then
# The current shell works already!
:
else
# Try alternative shells that (sometimes) support functions
for cmd in sh bash ash bsh ksh zsh sh5; do
set IFS=:; X="$PATH:/bin:/usr/bin:/usr/afsws/bin:/usr/ucb"; echo $X`
for dir
shell="$dir/$cmd"
if (test -f "$shell" || test -f "$shell.exe") &&
"$shell" -c 'foo () { exit 0; }; foo 2>/dev/null
then
# Re-execute with discovered functional shell
SHELL="$shell" exec "$shell" "$0" --re-executed ${1+"$@"}
fi
done
done
echo "Unable to locate a shell interpreter with function support" >&2
exit 1
fi
foo () {
echo "$SHELL: ta da!"
}
foo
exit 0
|
Note that this script finds a shell that supports functions of the
following syntax, since the use of the function keyword is much
less widely supported:
A notable exception to the assertion that all machines have a shell that
can handle functions is 4.3BSD, which has only a single shell: a
shell function deprived Bourne shell. There are two ways you can deal
with this:
-
Ask 4.3BSD users of your script to install a more featureful shell
such as bash, so that the technique above will work.
-
Have your script run itself through
sed , chopping itself into
pieces, with each function written to it's own script file, and then
feed what's left into the original shell. Whenever a function call is
encountered, one of the fragments from the original script will be
executed in a subshell.
If you decide to split the script with sed , you will need to
be careful not to rely on shell variables to communicate between
functions, since each `function' will be executed in its own subshell.
|