我使用bash
select
来创建一个多选对话框,当我在两个现有选项之间添加新选项时,选项编号会自动调整。
select choice in command1 command2 command3; do
$choice
break
done
为了显示与命令本身不同的内容,我被告知要声明一个关联数组
declare -A choices=(
[Option 1]=command1
[Option 2]=command2
[Option 3]=command3
)
select choice in "${!choices[@]}" exit ; do
[[ $choice == exit ]] && break
${choices[$choice]}
done
我不喜欢这种方式的一点是,exit
的选项被视为一个编号的选择。我想实现类似的目标
PS3="Select the desired option (q to quit): "
并使select
除了接受1
、2
或3
之外,还接受q
作为有效输入。
关联数组会导致输入用作索引这一事实出现问题,因此我切换到嵌套的case
。这样,我也不必声明单独的函数来存储多个命令
PS3="Select the desired option (q to quit): "
select choice in "Option 1" "Option 2" "Option 3"; do
case $choice in
"Option 1") command1a
command1b
break;;
"Option 2") command2a
command2b
break;;
"Option 3") command3a
command3b
break;;
q) echo "Bye!"
break;;
esac
done
现在不存在关于非数字(或超范围(输入的问题,但是作为输入的q
仍然没有被识别。它属于default
的情况,如果我已经定义了它,就执行*)
,如果我没有定义它,就简单地再次提示。
有什么方法可以实现我想要做的事情吗?
只需使用(检查的内容($REPLY
变量。
示例:
declare -A choices=(
[Show the date]=show_date
[Print calendar]=print_cal
[Say hello]=say_hello
)
show_date() {
date
}
print_cal() {
cal
}
say_hello() {
echo "Hello $USER"
}
PS3="Select the desired option (q to quit): "
select choice in "${!choices[@]}"
do
case "$choice" in
'') # handling the invalid entry - e.g. the "q"
# in a case of an invalid entry, the $choice is en empty(!) string
# checking the content of the entered line can be done using the $REPLY
case "$REPLY" in
q|Q) echo "Bye, bye - quitting...."; exit;;
*) echo "INVALID choice <$REPLY> - try again";;
esac
;;
*)
#valid user input
${choices[$choice]}
;;
esac
done
或者更短,但没有那么灵活的
declare -A choices=(
[Show the date]=show_date
[Print calendar]=print_cal
[Say hello]=say_hello
)
show_date() {
date
}
print_cal() {
cal
}
say_hello() {
echo "Hello $USER"
}
PS3="Select the desired option (q to quit): "
select choice in "${!choices[@]}"
do
case "$REPLY" in
q|Q) echo "Bye, bye - quitting...."; exit;;
1|2|3) ${choices[$choice]} ;;
*) echo "INVALID choice <$REPLY> - try again";;
esac
done