Bash or condition in a while statement
Solution 1
A sh
variant, and would remove the problems associated with ${var,,}
which uses the locale to convert strings (lowercase I
is not i
for everyone for instance):
#! /bin/sh -
while true; do
printf %s "Please enter your choice (stringA or stringB): "
IFS= read -r result || exit # exit on EOF
case $result in
([sS][tT][rR][iI][nN][gG][aAbB]) break
esac
echo >&2 Invalid choice.
done
Solution 2
That's because you want to use &&
, not ||
.
You want to repeat the loop if the result isn't stringA AND it isn't stringB. No string can be equal to both of them, which whould end your loop.
You can also use a pattern in [[ ... ]]
:
while [[ ${result,,} != string[ab] ]]
Solution 3
#!/bin/bash
echo "Please enter your choice (stringA or stringB): "
read result
while ! [ "${result,,}" = 'stringa' -o "${result,,}" = 'stringb' ]; do
echo Please enter only stringA or stringB:
read result
done
echo "You have selected $result!"
exit
In textspeech while not result is stringa or result is stringb do...
be aware of "
around your variables, else you will get an error if the var $result
is empty.
Solution 4
The issue in your code is that your loop loops while $result
is not the same as both stringA
and stringB
(at the same time). You may want to use
while [[ "${result,,}" != 'stringa' ]] && [[ "${result,,}" != 'stringb') ]]
or
until [[ "${result,,}" == 'stringa' ]] || [[ "${result,,}" == 'stringb') ]]
To get a user to pick one of a few choices, don't get them to type in long strings. Instead, provide them with a simple menu to pick from.
Suggestion:
#!/bin/bash
PS3='Your choice: '
select result in 'stringA' 'stringB'; do
case $REPLY in
[12])
break
;;
*)
echo 'Invalid choice' >&2
esac
done
printf 'You picked %s!\n' "$result"
Running this:
$ bash script.sh
1) stringA
2) stringB
Your choice: 3
Invalid choice
Your choice: 2
You picked stringB!
Related videos on Youtube
Georgi Stoyanov
Updated on September 18, 2022Comments
-
Georgi Stoyanov over 1 year
I want to write a script in bash which is checking the user input if it is equal to "stringA" or "stringB" and in case it is equal to one of these strings it should print the user input. My code is:
#!/bin/bash echo "Please enter your choice (stringA or stringB): " read result while [[ (${result,,} != 'stringa') || (${result,,} != 'stringb') ]]; do echo Please enter only stringA or stringB: read result done echo "You have selected $result!" exit
Unfortunately this code doesn't work and loop infinitely. I can only compare if the
$result
is equal to one of the strings removing the||
and the second part of the while loop. I have tried to replace the||
with-o
but I got the following error:./chk.sh: line 12: syntax error in conditional expression ./chk.sh: line 12: syntax error near `-o' ./chk.sh: line 12: `while [[ (${result,,} != 'stringa') -o (${result,,} != 'stringb') ]]; do'
-
smw over 6 years. . . De Morgan's Laws
-
-
ilkkachu over 6 yearsThey were using the
[[ ... ]]
construct, it doesn't have the same problem with unquoted variables as normal commands do. On the other hand, using-o
withtest
/[
, is a bit problematic since it can get confused about it if the other strings look like operators. Here, if$result
contains a!
(a lone exclamation point),[
drops an error. Instead, you can put the condition on the shell level and write[ some test ] || [ another test ]
(or use[[ .. ]]
and||
within it) -
Georgi Stoyanov over 6 years@FaxMax, it works very well, thank you very much!
-
Kusalananda almost 6 yearsThis is good, unless
stringA
andstringB
are just placeholders for longer strings, or strings that may be totally different from each other. -
Stéphane Chazelas almost 6 yearsTrue, though here it looks like the OP wants to explicitly allow users to enter
STRINGA
,sTringA
..., so allows for users to choose between 256 different valid values. -
Kusalananda almost 6 years@StéphaneChazelas Indeed.