Bash 脚本、case 语句和子菜单
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4728320/
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
Bash script, case statement and sub-menus
提问by ThG
I wish to run a script with a case statement leading to choices between other lists of choices (sort of sub-menus) between scripts :
我希望运行一个带有 case 语句的脚本,导致在脚本之间的其他选项列表(某种子菜单)之间进行选择:
#!/bin/bash
echo "Your choice ?"
echo "1) Foo"
echo "2) Bar"
echo "3) Stuff"
read case;
case $case in
#and this is where I would like to allow
#(here a simplified example I do not manage to code)
1) What script ? # may I use another case statement ?
a) Foo1;;
b) Foo2;;
2) What script ? # d°
a) Bar1;;
b) Bar2;;
c) Bar3;;
esac
Foo1, Foo2, Bar1, Bar2 and Bar3 being in fact bash scripts, I would like to call, eg, sh Foo1 from within the script.
Foo1、Foo2、Bar1、Bar2 和 Bar3 实际上是 bash 脚本,我想从脚本中调用例如 sh Foo1。
How must I proceed : May I include a case statement within a case statement (better than if statement, if the choices are numerous) ? And how do I call a script from within another script ?
我必须如何进行:我可以在 case 语句中包含 case 语句吗(如果选项很多,比 if 语句更好)?以及如何从另一个脚本中调用脚本?
Thanks in advance for your help
在此先感谢您的帮助
ThG
ThG
回答by Paused until further notice.
Yes, you can nest casestatements. You should also consider using a select statement instead of all those echoand readstatements.
是的,您可以嵌套case语句。您还应该考虑使用 select 语句而不是所有这些echo和read语句。
options=("Option 1" "Option 2" "Option3" "Quit")
optionsprompt='Please enter your choice: '
sub1=("Option 1 sub 1" "Option 1 sub 2")
sub1prompt='Please enter your choice: '
PS3=$optionsprompt
select opt in "${options[@]}"
do
case $opt in
"Option 1")
echo "you chose choice 1"
PS3=$sub1prompt
select sub1opt in "${sub1[@]}"
do
case $sub1opt in
"Option 1 sub 1")
echo "you chose choice 2"
;;
"Option 1 sub 2")
echo "you chose choice 2"
;;
esac
done
;;
"Option 2")
echo "you chose choice 2"
;;
"Option 2")
echo "you chose choice 3"
;;
"Quit")
break
;;
*) echo invalid option;;
esac
done
The first level menu would look like this:
第一级菜单如下所示:
1) Option 1
2) Option 2
3) Option3
4) Quit
Please enter your choice:
However, that can get very hairy very quickly. It would be better to break it up into functions where the inner select/casestatements are in separate functions or are abstracted so you can pass arguments to control them.
但是,这会很快变得非常毛茸茸。最好将其分解为函数,其中内部select/case语句位于单独的函数中或被抽象,以便您可以传递参数来控制它们。
To call another script, you might want to set a variable that holds the directory. It would look something like this:
要调用另一个脚本,您可能需要设置一个保存目录的变量。它看起来像这样:
basedir=/some/path
case ...
...
$basedir/Foo # call the script
回答by Rodrigue
Dennis' answershould do what you want. Just to illustrate how to do it with functions, so as to make the script more readable:
丹尼斯的回答应该做你想做的。只是为了说明如何用函数来做,以使脚本更具可读性:
function which_foo {
local foo_options=("foo1" "foo2" "cancel")
local PS3="Select foo: "
select foo in "${foo_options[@]}"
do
case $REPLY in
1) ./foo1.sh
break ;;
2) ./foo2.sh
break ;;
3) break ;;
esac
done
}
ACTIONS=("foo" "bar" "quit")
PS3="Select action: "
select action in "${ACTIONS[@]}"
do
case $action in
"foo") which_foo
break ;;
"bar") which_bar # Not present in this example
break ;;
"quit") break ;;
esac
done
As an aside, note:
顺便说一句,请注意:
- the use of
$REPLYin thecaseinsidewhich_foo, which is automatically set to the number selected by the user, instead of the text of the option. - the use of
breakin eachcaseoptions. Without them,selectputs you in a loop, so the user would be asked to enter a choice again. - that
selectnever changes the value ofPS3for you, so you have to do it yourself when switching between the different levels of your menu.
- 使用
$REPLYincaseinsidewhich_foo,它会自动设置为用户选择的数字,而不是选项的文本。 break在每个case选项中的使用。没有它们,select您将陷入循环,因此将要求用户再次输入选择。- 这
select永远不会改变您的价值PS3,因此在菜单的不同级别之间切换时,您必须自己做。

