Reputation: 365
I have a function which returns one of three values, 0, 1 or 2
I want to check the return value of the function in an if statement.
How can I do this in idiomatic bash?
This works, but looks very wrong to me:
vercomp $prev $new
result=$?
if [[ result -eq 1 ]]; then
echo "Greater than"
elif [[ result -eq 2 ]]; then
echo "Less than"
fi
How can I consolidate this code and use the function directly in the if statement instead of using the intermediate result variable and how can I access the return value without using $? ?
Everything I have tried has failed.
For example even this fails - why?
result=vercomp $prev $new
if [[ result -eq 1 ]]; then
echo "Greater than"
elif [[ result -eq 2 ]]; then
echo "Less than"
fi
And this fails:
if [[ vercomp $prev $new -eq 1 ]]; then
echo "Greater than"
elif [[ vercomp $prev $new -eq 2 ]]; then
echo "Less than"
fi
This fails:
if [[ $(vercomp $prev $new) -eq 1 ]]; then
echo "Greater than"
elif [[ $(vercomp $prev $new) -eq 2 ]]; then
echo "Less than"
fi
What am I doing wrong? How can I improve my working code?
Upvotes: 3
Views: 1525
Reputation: 85590
Bash functions return exit codes back to the shell which can be retrieved from the value of $?
as in your first case. You need to read through Return value in a Bash function to understand the difference between exit code and return value from function.
As explained in detail in multiple answers including Function return values within BASH if statements you can directly use the function invocation in the if
statement. A return code of 0
from the function would assert the if condition to true. So you can do something like
if vercomp "$prev" "$new"; then
printf 'return code zero \n'
else
case $? in
1) printf 'return code one \n' ;;
2) printf 'return code two \n' ;;
*) printf "unknown return code $?\n" ;;
esac
fi
As for the failure cases
result=vercomp $prev $new
is not even a valid function execution in bash but an incorrect variable assignment. To run function and store the output in a variable, you need to use Command Substitution $(..)
You need to have written it as result=$(vercomp "$prev" "$new")
if [[ vercomp $prev $new -eq 1 ]]; then
again is an incorrect invocation of the function. Everything inside [[..]]
is evaluated in a string context. So the test operator [[
just treats it as incorrect operation and would have thrown a parser error[[ $(vercomp $prev $new) -eq 1 ]]
is also incorrect. All commands in bash return an exit code to the shell the program is invoked from. The command substitution inherently returns the code to the shell via $?
but the -eq
operator checks for a string value returned from the invocation. Since the construct does not put any contents to stdout, there won't anything to match with 1 or 2. If you done soemthing like [[ $(vercomp "$prev" "$new"; printf "$?") -eq 1 ]]
it would have worked, but again not a good practice.Upvotes: 2
Reputation: 88646
With bash:
case $? in
0) echo "one";;
1) echo "two";;
2) echo "three";;
esac
See: help case
Upvotes: 1