Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does a syntax error in a while loop interrupt the script (but does not outside the while loop)

Tags:

linux

bash

shell

Consider these three bash scripts:

  • script without a syntax error - executes without errors, as expected, loops "this is the end: -1":
#!/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
  • script which results in a syntax error (note the missing x and y variables, which are then needed for a calculation):
#!/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 "-  ")
  • script without a while loop - script execution is not interrupted:
#!/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.

like image 644
Tomasz Avatar asked Feb 13 '26 11:02

Tomasz


1 Answers

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.

like image 195
tripleee Avatar answered Feb 16 '26 01:02

tripleee



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!