Bash or condition in a while statement

19,017

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!
Share:
19,017

Related videos on Youtube

Georgi Stoyanov
Author by

Georgi Stoyanov

Updated on September 18, 2022

Comments

  • Georgi Stoyanov
    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' 
    
  • ilkkachu
    ilkkachu over 6 years
    They were using the [[ ... ]] construct, it doesn't have the same problem with unquoted variables as normal commands do. On the other hand, using -o with test/[, 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
    Georgi Stoyanov over 6 years
    @FaxMax, it works very well, thank you very much!
  • Kusalananda
    Kusalananda almost 6 years
    This is good, unless stringA and stringB are just placeholders for longer strings, or strings that may be totally different from each other.
  • Stéphane Chazelas
    Stéphane Chazelas almost 6 years
    True, 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
    Kusalananda almost 6 years
    @StéphaneChazelas Indeed.