Reputation: 16843
I've written the following minimal example to demonstrate
The following does NOT work:
#! /bin/bash
n=1 m=2
while (( n < m ))
echo "$n $m"
(( n=n+1 ))
do
continue
done
The following DOES work:
#! /bin/bash
n=1 m=2
while true
echo "$n $m"
(( n=n+1 ))
do
if (( n < m ))
then
continue
else
break
fi
done
I understand why the second form works. I do not understand why the first form doesn't work.
I wrote these scripts thinking they would be equivalent. (Produce the same output.) However the first loops infinity! Why does this happen?
Upvotes: 0
Views: 3208
Reputation: 295472
First, a quick look at the documentation:
$ help while
while: while COMMANDS; do COMMANDS; done
Expand and execute COMMANDS as long as the final command in the
`while' COMMANDS has an exit status of zero.
Note the exact text: the final command in the while
COMMANDS is the one whose exit status counts. We'll return to that later.
In your original code:
while (( n < m ))
echo "$n $m"
(( n=n+1 ))
do
continue
done
...you aren't checking whether (( n < m ))
is true as your condition; instead, you're checking whether (( n = n + 1 ))
is true.
This is true because everything before the do
is composed to form the condition that determines whether to continue running the loop, and the exit status of a series of commands separated by newlines or ;
s is the exit status of the last command in that series. The only case where (( n = n + 1 ))
would not be true (assuming no contents that can't be coerced to an integer or otherwise cause an error) is if the initial value were below 0, and thus the result were 0 or less.
If you really want all those commands to be inside your condition, you could instead write:
while (( n < m )) && echo "$n $m" && (( n = n + 1 )); do :; done
...though of course that has somewhat different behavior (not 'echo'ing if the comparison has failed).
Consider instead:
while (( n < m )); do
echo "$n $m"
(( n++ ))
done
Upvotes: 3