退出 bash switch 语句

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7034838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:52:32  来源:igfitidea点击:

Exit a bash switch statement

bash

提问by Moses

I've written a menu driven bash script that uses a switch caseinside of a whileloop to perform the various menu options. Everything works just fine. Now I'm trying to improve the program by performing error testing on the user input, but I cannot seem to make it work...

我编写了一个菜单驱动的 bash 脚本,它使用循环switch case内部while来执行各种菜单选项。一切正常。现在我试图通过对用户输入执行错误测试来改进程序,但我似乎无法让它工作......

The problem is I don't know how to properly break out of a switch statement, without breaking out of the while loop (so the user can try again).

问题是我不知道如何正确跳出 switch 语句,而不跳出 while 循环(因此用户可以再试一次)。

# repeat command line indefinitely until user quits
while [ "$done" != "true" ]
do
   # display menu options to user
   echo "Command Menu" # I cut out the menu options for brevity....

   # prompt user to enter command
   echo "Please select a letter:"
   read option

   # switch case for menu commands, accept both upper and lower case
   case "$option" in

   # sample case statement
   a|A) echo "Choose a month"
        read monthVal
        if [ "$monthVal" -lt 13 ]
        then 
           cal "$monthVal"
        else
           break # THIS DOES NOT WORK. BREAKS WHILE LOOP, NOT SWITCH!
        fi
        ;;
   q|Q) done="true" #ends while loop
        ;;
   *)   echo "Invalid option, choose again..."
        ;;
   esac
done
exit 0

The program works fine when the user enters a valid month value, but if they enter a number higher than 13, instead of breaking the switch statement and repeating the loop again, the program breaks both the switch and while loop and stops running.

当用户输入有效的月份值时,程序运行良好,但如果输入的数字大于 13,则程序不会中断 switch 语句并再次重复循环,而是中断 switch 和 while 循环并停止运行。

回答by John Kugelman

Hitting ;;will terminate the case statement. Try not doing anything at all:

点击;;将终止 case 语句。尝试什么都不做:

a|A) echo "Choose a month"
     read monthVal
     if [ "$monthVal" -lt 13 ]
     then 
        cal "$monthVal"
     fi
     ;;

回答by glenn Hymanman

Move the body of that caseinto a function, and you can returnfrom the function at will.

将它的主体移动case到一个函数中,您可以随意return从该函数中取出。

do_A_stuff() {
    echo "Choose a month"
    read monthVal
    if [ "$monthVal" -lt 13 ]
    then 
       cal "$monthVal"
    else
       return
    fi
    further tests ...
}

Then

然后

case $whatever in
a|A) do_A_stuff ;;

回答by Phil

I think what you mean to do with breakis "quit this case statement and restart the while loop". However, case ... esacisn't a control-flow statement (although it may smell like one), and doesn't pay attention to break.

我认为你的意思break是“退出这个 case 语句并重新启动 while 循环”。然而,case ... esac不是控制流语句(虽然它可能闻起来像一个),并且不注意break.

Try changing breakinto continue, which will send control back to the start of the while loop.

尝试更改breakcontinue,这会将控制发送回 while 循环的开始。

回答by Lionel

In your example, there is no point in breaking, you can omit the else break statement altogether.

在您的示例中,中断没有意义,您可以完全省略 else break 语句。

The problem occurs when there is code that runs after the point where you would have broken. You'd want to write something like that

当代码在您可能会破坏的点之后运行时,就会出现问题。你想写这样的东西

case $v in
a) if [ $x ]; then bla; else break; fi;
  some more stuff ;;
b) blablabla ;;

What I usually do (because creating a function is such a hassle with copy pasting, and mostly it breaks the flow of the program when you read it to have a function somewhere else) is to use a break variable (which you can call brake for fun when you have a lame sense of humor like me) and enclose "some more stuff" in an if statement

我通常做的(因为创建一个函数是复制粘贴的一个麻烦,而且当你阅读它以在其他地方拥有一个函数时,它通常会中断程序的流程)是使用一个中断变量(你可以调用它来刹车)当你像我一样有蹩脚的幽默感时会很有趣)并在 if 语句中包含“更多的东西”

case $v in
a) if [ $x ]; then bla; else brake="whatever that's not an empty string"; fi;
   if [ -z "$brake" ];then some more stuff; brake=""; fi;; 
   #don't forget to clear brake if you may come back here later.
b) blablabla ;;
esac

回答by Dumbled0re

This should do the trick: Wrap the code in a one-trip for-loop:

这应该可以解决问题:将代码包装在单程 for 循环中:

#! /bin/bash

case foo in
  bar)
    echo "Should never get here."
    ;;

  foo)
    for just in this_once ; do
      echo "Top half only."
      if ! test foo = bar; then break; fi
      echo "Bottom half -- should never get here."
    done
    ;;

  *)
    echo "Should never get here either."
    ;;
esac