Bash scripting, multiple conditions in while loop
Solution 1
The correct options are (in increasing order of recommendation):
# Single POSIX test command with -o operator (not recommended anymore).
# Quotes strongly recommended to guard against empty or undefined variables.
while [ "$stats" -gt 300 -o "$stats" -eq 0 ]
# Two POSIX test commands joined in a list with ||.
# Quotes strongly recommended to guard against empty or undefined variables.
while [ "$stats" -gt 300 ] || [ "$stats" -eq 0 ]
# Two bash conditional expressions joined in a list with ||.
while [[ $stats -gt 300 ]] || [[ $stats -eq 0 ]]
# A single bash conditional expression with the || operator.
while [[ $stats -gt 300 || $stats -eq 0 ]]
# Two bash arithmetic expressions joined in a list with ||.
# $ optional, as a string can only be interpreted as a variable
while (( stats > 300 )) || (( stats == 0 ))
# And finally, a single bash arithmetic expression with the || operator.
# $ optional, as a string can only be interpreted as a variable
while (( stats > 300 || stats == 0 ))
Some notes:
Quoting the parameter expansions inside
[[ ... ]]
and((...))
is optional; if the variable is not set,-gt
and-eq
will assume a value of 0.Using
$
is optional inside(( ... ))
, but using it can help avoid unintentional errors. Ifstats
isn't set, then(( stats > 300 ))
will assumestats == 0
, but(( $stats > 300 ))
will produce a syntax error.
Solution 2
Try:
while [ $stats -gt 300 -o $stats -eq 0 ]
[
is a call to test
. It is not just for grouping, like parentheses in other languages. Check man [
or man test
for more information.
jake9115
Updated on August 09, 2022Comments
-
jake9115 almost 2 years
I'm trying to get a simple while loop working in bash that uses two conditions, but after trying many different syntax from various forums, I can't stop throwing an error. Here is what I have:
while [ $stats -gt 300 ] -o [ $stats -eq 0 ]
I have also tried:
while [[ $stats -gt 300 ] || [ $stats -eq 0 ]]
... as well as several others constructs. I want this loop to continue while
$stats is > 300
or if$stats = 0
. -
danfuzz about 11 yearsActually,
[[
is generally the preferred built-in to introduce a test expression. It has several advantages over the older single[
syntax. -
danfuzz about 11 yearsI recommend
[[
over[
. See my comment on the other answer. -
drewmm about 11 yearsThat's fair. I used [ ] because that was what the OP was trying to use. I've seen both used with success.
-
jake9115 about 11 yearsFantastic answer, amazingly thorough
-
SaxDaddy over 9 yearsBravo. a classic way to answer a post. Well done. I'm assuming you can use the same syntax with
until
as well, yes? -
chepner over 9 years@SaxDaddy More or less, as long as you take care to negate the conditions correctly:
while [ foo -o bar ]
becomesuntil ! [ foo -o bar ]
, butwhile foo || bar
becomesuntil ! foo && ! bar
. -
msimmer92 over 5 years@danfuzz I know this is an old thread, but it would be great if you cite this in case people wanna read exactly why [[ is preferred over [. I know everyone can Google on their own... but still, it's good practice to cite.. makes your comment more robust and the reader's search faster and more efficient.
-
uldics over 3 yearsSeems this does not work when reading incoming data:
while [[ read -r line && $inputdata != "" ]]; do
. How do I achieve that? -
Admin over 2 yearsWhen reading incoming data you can for example use this form for multiple conditions:
while read -r theline && [ "$theline" != "" ]
-
Arash about 2 years@chepner could you please help me with my condition:
while [[ $counter -le 97 -a "$breakCond" -le "$Mu"]]
-
chepner about 2 years
-a
is not recognized inside[[...]]
; use&&
.