Korn 中的无限 while 循环 Shell

Infinite while loop in Korn Shell

我有以下代码:

#!/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

如果您想知道,while [ x$opt = "x" ] 表示 "while $opt is empty"。

这是输出:

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] :

因此,当什么都不输入或输入意想不到的内容时,它会循环,好的。 但是为什么当它应该提示最后一个 echo 消息时,它仍然在键入 1/2/3 和 4 时循环?

编辑: 我在 while 循环中添加了一个 echo $opt,它向我打印了这个:

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

所以 $opt 收到了它应该接收的用户输入,但是 while 仍然没有中断。

您可能希望使用更简洁的 case 表达式来避免多个 if 条件:

#!/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"

关于你的问题,你不需要||条件之间,你实际上需要使用&&来检查所有否定条件:

#!/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"

另外,在 [ ... ] 中引用 $opt 也很重要,如我的回答所示。

[ $opt != "1" ] || [ $opt != "2" ] 总是 为真,无论 $opt 具有什么值。

因此,该行为是正常的。