Consider these three bash scripts:
#!/bin/bash
while true ; do
x=1 # or, read the variable from some external source
y=2 # or, read the variable from some external source
z=$(( $x - $y ))
echo "this is the result: $z"
sleep 1
done
Execution - infinite loop, until we interrupt:
$ bash test.sh
this is the result: -1
this is the result: -1
this is the result: -1
^C
#!/bin/bash
while true ; do
x= # or, read the variable from some external source
y= # or, read the variable from some external source
z=$(( $x - $y ))
echo "this is the result: $z"
sleep 1
done
Execution - bash interrupts script execution when there is a syntax error:
$ bash test.sh
test.sh: line 6: - : syntax error: operand expected (error token is "- ")
#!/bin/bash
x=
y=
z=$(( $x - $y ))
echo "this is the result: $z"
Execution - bash notices a syntax error in calculation, but does NOT interrupt script execution:
$ bash test.sh
test.sh: line 5: - : syntax error: operand expected (error token is "- ")
this is the result:
Why does bash behave differently upon getting a syntax error, depending on whether it's in a while loop or not? EDIT: I'm aware input variables could/should be verified, and there are various ways to do it. I was more interested why it behaves differently, depending on whether we're in a while loop or not.
The difference is not whether it's in a loop or not; the difference is that the variable is empty.
$ bash # start a fresh instance
bash$ x=''
bash$ y=''
bash$ $(( $x - $y ))
bash: - : syntax error: operand expected (error token is " ")
As noted by @oguzismail in a comment, the syntax error actually doesn't cause the whole script to exit; it causes the compound command (i.e. the while loop) to abort. You can demonstrate this by adding echo "still here" after the done line.
If you want to prevent this from happening when you receive x and y from an external source, maybe check if they contain any non-numeric characters?
case ${x#-}${y#-} in
*[!0-9]*)
echo "$0: error; $x and $y need to be strictly numeric" >&2
exit 74;;
esac
Notice the hack to trim off a single minus sign if present by way of a parameter expansion.
As @LéaGris points out, in Bash, you could also simply say declare -i x y to have the shell constrain the possible values for x and y to integers; then they will be coerced to 0 if they receive invalid values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With