In this lesson, you will learn how to capture structured data from your functions while maintaining clean error reporting using status codes and local variables.
The Problem with Bash "Returns"
In many programming languages, a function can return complex data types like lists or objects. In Bash, the return keyword is strictly reserved for exit status codes (0 for success, 1–255 for errors). If you try to return "some string", your script will crash. To bypass this, we use a two-part idiom: using stdout to pass data and exit codes to pass success state.
Capturing Output with Local Variables
To retrieve a value from a function, we use command substitution $(...). Inside the function, we use local variables to prevent cluttering the global environment, then echo the result. Because stdout is used for the data, we must reserve the exit status exclusively for error signaling.
calculate_sum() {
local a=$1
local b=$2
# Check for valid input
if [[ -z "$a" || -z "$b" ]]; then
return 1
fi
# Send result to stdout
echo $((a + b))
return 0
}
# Capture the result
result=$(calculate_sum 5 10)
if [[ $? -eq 0 ]]; then
echo "The sum is: $result"
else
echo "Calculation failed."
fi
Why this Idiom Matters
- Separation of Concerns: By using
echofor data andreturnfor state, you ensure your script behaves predictably. If a function encounters an error, it can signal that viareturn 1without accidentally sending a "garbage" value to yourresultvariable. - Local Scope: Always define your variables inside the function using
local. This ensures that your function doesn't accidentally overwrite a variable in your main script that happens to share the same name. - Capture Clarity: By assigning the output to a variable using
$(), you make the flow of data explicit, which is vital when you start writing larger, more complex scripts.
Key Takeaway: Use echo to output data from a function and return solely to signal success or failure status.