Bash Function Return Values and Exit
For those lucky souls out there programming in bash, you may be making use of the bash subshell trick that allows you to "return" a value from a function.
Will produce the output,
The tricky gotcha in this situation involves exiting on error conditions. For example, consider the following enhancement to echoTwice,
You would expect to see the error message and nothing else. However, instead you see
Why does this happen? It happens because the assignment to $twice happens via a subshell. A subshell is spawned to evaluate the result of echoTwice. When that subshell exits early, bash treats it no differently than had the whole function proceded. Subsequently, rather than quitting your code, processing continues when the subshell completes. So, how do you accomodate this in your code without resorting to ugly globals?
The solution that I have found is to test if $twice was assigned.
The reason I can't just check the exit status is because
EDIT (Nov 2nd, 11): It turns out that you can check the return status! The issue is accurately described that declare twice= has its own exit status, but the exit status arises from the use of the bash built-in "declare" and NOT from the assignment to the variable (See the "declare" section of http://www.gnu.org/software/bash/manual/bashref.html#Bash-Builtins). So, the solution becomes:
function echoTwice() { echo "$1" echo "$1" } declare twice=$(echoTwice "woot") echo "Twice is: $twice"
Will produce the output,
Twice is: woot woot
The tricky gotcha in this situation involves exiting on error conditions. For example, consider the following enhancement to echoTwice,
function echoTwice() { if [ -z "$1" ]; then echo "Must provide an argument" >&2 exit 1 fi echo "$1" echo "$1" } declare twice=$(echoTwice) echo "Twice is: $twice"
You would expect to see the error message and nothing else. However, instead you see
Must provide an argument Twice is:
Why does this happen? It happens because the assignment to $twice happens via a subshell. A subshell is spawned to evaluate the result of echoTwice. When that subshell exits early, bash treats it no differently than had the whole function proceded. Subsequently, rather than quitting your code, processing continues when the subshell completes. So, how do you accomodate this in your code without resorting to ugly globals?
The solution that I have found is to test if $twice was assigned.
if [ -z "$twice" ]; then # Error message emitted by echoTwice prints to STD_ERR and # ...will not be consumed by the sub-shell exit 1 fi
The reason I can't just check the exit status is because
declare twice=
is an actual execution and will typically have a valid exit status.EDIT (Nov 2nd, 11): It turns out that you can check the return status! The issue is accurately described that declare twice= has its own exit status, but the exit status arises from the use of the bash built-in "declare" and NOT from the assignment to the variable (See the "declare" section of http://www.gnu.org/software/bash/manual/bashref.html#Bash-Builtins). So, the solution becomes:
declare twice= twice=$(echoTwice) if [ $? -ne 0 ]; then # Error message emitted by echoTwice prints to STD_ERR and # ...will not be consumed by the sub-shell exit 1 fi echo "Twice is: $twice"
Comments