选择:接受不公开的字符输入

时间:2016-11-06 09:01:05

标签: bash select case exit

我正在使用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): "

除了selectq1之外,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案例,如果我已经定义它,则执行*),或者只是在我没有提示时再次提示。

有没有办法实现我想要做的事情?

1 个答案:

答案 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