Will
Will

Reputation: 2410

Infinite while loop in Korn Shell

I have the following code :

#!/bin/ksh
echo "1) Option 1"
echo "2) Option 2"
echo "3) Option 3"
echo "4) Option 4"

opt=0
while [ x$opt = "x" ] || [ $opt != "1" ] || [ $opt != "2" ] || [ $opt != "3" ] || [ $opt != "4" ]; do
        printf "Enter [1|2|3|4] : "
        read -r opt
done

echo "Option selected : $opt

The while [ x$opt = "x" ] means "while $opt is empty" in case you wonder.

Here's the output :

Will:/home/will> ./script.ksh
Enter [1|2|3|4] :
Enter [1|2|3|4] : jde
Enter [1|2|3|4] : 1
Enter [1|2|3|4] : 2
Enter [1|2|3|4] : 3
Enter [1|2|3|4] : 4
Enter [1|2|3|4] :

So when typing nothing or something unexpected it loops, OK. But why does it still loops when 1/2/3 and 4 are typed when it should prompt the last echo message ?

EDIT : I have added a echo $opt in the while loop, and it prints me this :

Enter [1/2/3/4] : d
d
Enter [1/2/3/4] : 1
1
Enter [1/2/3/4] :

So $opt received the user input as it should, but the while still never breaks.

Upvotes: 1

Views: 3361

Answers (2)

anubhava
anubhava

Reputation: 785761

You may want to avoid multiple if conditions using much cleaner case expressions:

#!/bin/ksh

echo "1) Option 1"
echo "2) Option 2"
echo "3) Option 3"
echo "4) Option 4"

while true
do
   case $opt in
     1|2|3|4)
         break ;;
     *)
         printf "Enter [1|2|3|4] : "
         read -r opt ;;
   esac
done

echo "Option selected : $opt"

About your problem, you don't need || between conditions, you actually need to use && to check for all negative conditions:

#!/bin/ksh
echo "1) Option 1"
echo "2) Option 2"
echo "3) Option 3"
echo "4) Option 4"

opt=
while [ "x$opt" = "x" ] && [ "$opt" != "1" ] && [ "$opt" != "2" ] && [ "$opt" != "3" ] && [ "$opt" != "4" ]; do
        printf "Enter [1|2|3|4] : "
        read -r opt
done

echo "Option selected : $opt"

Also it is important to quote $opt inside [ ... ] as shown in my answer.

Upvotes: 1

Alexandre Fenyo
Alexandre Fenyo

Reputation: 4819

[ $opt != "1" ] || [ $opt != "2" ] will always be true, whatever value $opt has.

Therefore, the behaviour is normal.

Upvotes: 1

Related Questions