Bash 脚本中的多选菜单

Bash 脚本中的多选菜单

我是 bash 新手,但我想创建一个脚本,让用户从选项列表中选择多个选项。

本质上我想要的是类似于下面的例子:

       #!/bin/bash
       OPTIONS="Hello Quit"
       select opt in $OPTIONS; do
           if [ "$opt" = "Quit" ]; then
            echo done
            exit
           elif [ "$opt" = "Hello" ]; then
            echo Hello World
           else
            clear
            echo bad option
           fi
       done

(来源:http://www.faqs.org/docs/Linux-HOWTO/Bash-Prog-Intro-HOWTO.html#ss9.1

但是我的脚本会有更多的选项,我想允许选择多个。所以像这样:

1)选项 1
2)选项 2
3)选项 3
4)选项 4
5)完成

对他们选择的选项提供反馈也很好,例如在他们已经选择的选项旁边加上加号。例如,如果您选择“1”,我希望清除页面并重新打印:

1) Option 1 +
2) Option 2
3) Option 3
4) Option 4
5) Done

那么如果你选择“3”:

1) Option 1 +
2) Option 2
3) Option 3 +
4) Option 4
5) Done

另外,如果他们再次选择(1),我希望它“取消选择”该选项:

1) Option 1
2) Option 2
3) Option 3 +
4) Option 4
5) Done

最后,当按下“完成”时,我希望在程序退出之前显示所选内容的列表,例如,如果当前状态是:

1) Option 1
2) Option 2 +
3) Option 3 + 
4) Option 4 +
5) Done

按 5 应该打印:

Option 2, Option 3, Option 4

...脚本终止。

所以我的问题是 - 这在 bash 中是否可行,如果可行,是否有人可以提供代码示例?

如有任何建议我将非常感激。

答案1

我认为你应该看看对话或者鞭尾

对话框

编辑:

以下是使用问题中的选项的示例脚本:

#!/bin/bash
cmd=(dialog --separate-output --checklist "Select options:" 22 76 16)
options=(1 "Option 1" off    # any option can be set to default to "on"
         2 "Option 2" off
         3 "Option 3" off
         4 "Option 4" off)
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
clear
for choice in $choices
do
    case $choice in
        1)
            echo "First Option"
            ;;
        2)
            echo "Second Option"
            ;;
        3)
            echo "Third Option"
            ;;
        4)
            echo "Fourth Option"
            ;;
    esac
done

答案2

如果你认为whiptail这很复杂,下面是一段仅用于 bash 的代码,它可以完成以下操作:确切地您想要的。它很短(约 20 行),但对于初学者来说有点神秘。除了显示选中选项的“+”外,它还为每个用户操作提供反馈(“无效选项”、“选项 X 已选中”/未选中等)。

话虽如此,你还是可以做到的!

希望你喜欢...这是一个非常有趣的挑战:)

#!/bin/bash

# customize with your own.
options=("AAA" "BBB" "CCC" "DDD")

menu() {
    echo "Avaliable options:"
    for i in ${!options[@]}; do 
        printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${options[i]}"
    done
    if [[ "$msg" ]]; then echo "$msg"; fi
}

prompt="Check an option (again to uncheck, ENTER when done): "
while menu && read -rp "$prompt" num && [[ "$num" ]]; do
    [[ "$num" != *[![:digit:]]* ]] &&
    (( num > 0 && num <= ${#options[@]} )) ||
    { msg="Invalid option: $num"; continue; }
    ((num--)); msg="${options[num]} was ${choices[num]:+un}checked"
    [[ "${choices[num]}" ]] && choices[num]="" || choices[num]="+"
done

printf "You selected"; msg=" nothing"
for i in ${!options[@]}; do 
    [[ "${choices[i]}" ]] && { printf " %s" "${options[i]}"; msg=""; }
done
echo "$msg"

答案3

这是一种仅使用 Bash 功能而无需任何外部依赖项即可完成您想要的操作的方法。它标记当前选择并允许您切换它们。

#!/bin/bash
# Purpose: Demonstrate usage of select and case with toggleable flags to indicate choices
# 2013-05-10 - Dennis Williamson

choice () {
    local choice=$1
    if [[ ${opts[choice]} ]] # toggle
    then
        opts[choice]=
    else
        opts[choice]=+
    fi
}

PS3='Please enter your choice: '
while :
do
    clear
    options=("Option 1 ${opts[1]}" "Option 2 ${opts[2]}" "Option 3 ${opts[3]}" "Done")
    select opt in "${options[@]}"
    do
        case $opt in
            "Option 1 ${opts[1]}")
                choice 1
                break
                ;;
            "Option 2 ${opts[2]}")
                choice 2
                break
                ;;
            "Option 3 ${opts[3]}")
                choice 3
                break
                ;;
            "Option 4 ${opts[4]}")
                choice 4
                break
                ;;
            "Done")
                break 2
                ;;
            *) printf '%s\n' 'invalid option';;
        esac
    done
done

printf '%s\n' 'Options chosen:'
for opt in "${!opts[@]}"
do
    if [[ ${opts[opt]} ]]
    then
        printf '%s\n' "Option $opt"
    fi
done

对于 ksh,更改函数的前两行:

function choice {
    typeset choice=$1

和 的一切#!/bin/ksh

答案4

我使用了 MestreLion 的示例并起草了下面的代码。您需要做的就是更新前两部分中的选项和操作。

#!/bin/bash
#title:         menu.sh
#description:   Menu which allows multiple items to be selected
#author:        Nathan Davieau
#               Based on script from MestreLion
#created:       May 19 2016
#updated:       N/A
#version:       1.0
#usage:         ./menu.sh
#==============================================================================

#Menu options
options[0]="AAA"
options[1]="BBB"
options[2]="CCC"
options[3]="DDD"
options[4]="EEE"

#Actions to take based on selection
function ACTIONS {
    if [[ ${choices[0]} ]]; then
        #Option 1 selected
        echo "Option 1 selected"
    fi
    if [[ ${choices[1]} ]]; then
        #Option 2 selected
        echo "Option 2 selected"
    fi
    if [[ ${choices[2]} ]]; then
        #Option 3 selected
        echo "Option 3 selected"
    fi
    if [[ ${choices[3]} ]]; then
        #Option 4 selected
        echo "Option 4 selected"
    fi
    if [[ ${choices[4]} ]]; then
        #Option 5 selected
        echo "Option 5 selected"
    fi
}

#Variables
ERROR=" "

#Clear screen for menu
clear

#Menu function
function MENU {
    echo "Menu Options"
    for NUM in ${!options[@]}; do
        echo "[""${choices[NUM]:- }""]" $(( NUM+1 ))") ${options[NUM]}"
    done
    echo "$ERROR"
}

#Menu loop
while MENU && read -e -p "Select the desired options using their number (again to uncheck, ENTER when done): " -n1 SELECTION && [[ -n "$SELECTION" ]]; do
    clear
    if [[ "$SELECTION" == *[[:digit:]]* && $SELECTION -ge 1 && $SELECTION -le ${#options[@]} ]]; then
        (( SELECTION-- ))
        if [[ "${choices[SELECTION]}" == "+" ]]; then
            choices[SELECTION]=""
        else
            choices[SELECTION]="+"
        fi
            ERROR=" "
    else
        ERROR="Invalid option: $SELECTION"
    fi
done

ACTIONS

相关内容