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.