bash脚本中的多选菜单

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

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

#!/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 )

但是,我的脚本将有更多的select,我想要允许select多个。 所以像这样的东西:

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

对他们select的人进行反馈也是很好的,例如在他们已经select的旁边加上符号。 例如,如果您select“1”,我想页面清除并重新打印:

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

那么如果你select“3”:

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

另外,如果他们再次select(1)我想要“取消”选项:

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

最后当按下完成时,我想要列出在程序退出之前被select显示的列表,例如,如果当前状态是:

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

按5应该打印:

 Option 2, Option 3, Option 4 

…脚本终止。

所以我的问题 – 这是可能的bash,如果是的话是任何人都可以提供一个代码示例?

任何意见将不胜感激。

我想你应该看看对话或whiptail 。

dialog box

编辑:

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

 #!/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 

如果你认为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 [[ "$msg" ]] && echo "$msg"; : } 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" 

这里有一种方法可以只使用Bash特性而不需要外部依赖。 它标志着当前的select,并允许你切换它们。

 #!/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 

和shebang到#!/bin/ksh

我写了一个名为问卷的图书馆,这是一个用于创build命令行问卷的迷你DSL。 它提示用户回答一系列问题,并将答案打印到标准输出。

这使你的任务变得非常简单。 用pip install questionnaire并创build一个脚本,例如questions.py ,如下所示:

 from questionnaire import Questionnaire q = Questionnaire(out_type='plain') q.add_question('options', prompt='Choose some options', prompter='multiple', options=['Option 1', 'Option 2', 'Option 3', 'Option 4'], all=None) q.run() 

然后运行python questions.py 。 当你完成回答他们打印到标准输出的问题。 它适用于Python 2和3,其中之一几乎肯定安装在您的系统上。

它也可以处理更复杂的问卷,以防万一谁想这样做。 以下是一些function:

  • 将答案打印为JSON(或纯文本)作为标准输出
  • 允许用户返回并回答问题
  • 支持有条件的问题(问题可能取决于以前的答案)
  • 支持以下types的问题:原始input,select一个,select多个
  • 问题expression和答案值之间没有强制的联系

我使用了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 
 export supermode=none source easybashgui list "Option 1" "Option 2" "Option 3" "Option 4"