【问题标题】:Infinite while loop in Korn ShellKorn Shell 中的无限 while 循环
【发布时间】:2017-09-23 17:14:53
【问题描述】:

我有以下代码:

#!/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" ] 的意思是“$opt 为空”,以防您想知道。

这是输出:

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

所以当没有输入任何内容或出现意外情况时,它会循环,OK。 但是为什么当它应该提示最后一个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 仍然没有中断。

【问题讨论】:

    标签: shell while-loop ksh


    【解决方案1】:

    您可能希望使用更简洁的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 也很重要。

    【讨论】:

    • 当使用&& 而不是|| 时,我的代码直接与输出option selected : 0 一起存在。当我删除 [ "x$opt" = "x" ] 时它可以工作,但这种情况下如果用户不输入任何内容,脚本就会崩溃
    • 检查最新编辑的答案。我将 opt=0 更改为 opt= 并更改了引号。
    • 我已经添加了引号并从 $opt 声明中删除了 0,现在它给了我 ./t[7]: test: argument expected :/
    • 谢谢 - 我选择了基于案例的解决方案,在我看来它更简洁,而且效果很好 :) 谢谢!
    • 编辑以使case 解决方案成为主要答案。如果您只检查一个表达式,它比多个 [...] 测试要好得多
    【解决方案2】:

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

    因此,行为是正常的。

    【讨论】:

      猜你喜欢
      • 2016-06-05
      • 2011-12-16
      • 2014-03-29
      • 1970-01-01
      • 2012-12-24
      • 2015-06-25
      • 2013-02-22
      • 2011-11-19
      • 1970-01-01
      相关资源
      最近更新 更多