我正在使用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
,q
或1
之外,2
接受3
作为有效输入。
关联数组导致输入被用作索引的问题,所以我切换到嵌套的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
案例,如果我已经定义它,则执行*)
,或者只是在我没有提示时再次提示。
有没有办法实现我想要做的事情?
答案 0 :(得分:1)
只需使用{检查$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