I’m new to bash scripting and trying to write the following simple
function wait_some {
if [ -z $1 ];
echo some_string
then if ! [[ $1 =~ ^[0-9]+([.][0-9]+)?$ ]];
then
echo "$1 is not a number"
exit 2
else echo "it's a number"
fi
fi
}
wait_some 2.2 //prints some_string and then it's a number
And this works as expected.
But if I delete echo “some string’ it prints nothing:
function wait_some {
if [ -z $1 ];
then if ! [[ $1 =~ ^[0-9]+([.][0-9]+)?$ ]];
then
echo "$1 is not a number"
exit 2
else echo "it's a number"
fi
fi
}
wait_some 2.2 //prints nothing
Why? Why does deleting echo some_string right after the condition checking breaks the function?
Advertisement
Answer
It is because the if-condition is executed as a compound statement in bash i.e. command1;command2 and also incorrect usage of -z in the test operator.
I will explain it with the debugging I did with the set -x option for both the examples.
For the successful, this is what the execution sequence is
++ wait_some 2.2 ++ '[' -z 2.2 ']' ++ echo some_string some_string
As you can see the two-conditions getting executed [ -z 2.2 ] is failing. But why? Because the string has a non-zero length (See how -z works) and the check is yielding a failure of the condition, which should have been [ ! -z 2.2 ]. And it does not end at that.
Because of the combined set of commands you have used, command1;command2 the command1 the failing if-condition, now command2 which is just a plain echo runs successfully with a positive return code making the overall if-condition successful, leading to the regex search and you are able to see the subsequent echo'ed statement.
Now for the failure case, the expanded result from set -x looks like
++ wait_some 2.2 ++ '[' -z 2.2 ']'
As you can see, on removing the echo statement, the overall return code for the if-condition has become false and the inner conditions are not exercised at all. Also removing the echo statement is similar to actually adding a false operator in the script like
if [ -z $1 ];
false
which would have expanded into
++ wait_some 2.2 ++ '[' -z 2.2 ']' ++ false
leading to the failure of your condition. The ideal way your script should have been coded is something like
#/bin/bash
# See the updated if-condition and code reorganization
function wait_some {
if [ ! -z "$1" ];
then
if ! [[ $1 =~ ^[0-9]+([.][0-9]+)?$ ]];
then
echo "$1 is not a number"
exit 2
else echo "it's a number"
fi
fi
}
wait_some 2.2
The best thing about your error is even http://www.shellcheck.net/ couldn’t identify the incorrect syntax in the if-condition and asserted the script didn’t have any issues.