AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 1705
In Process
Daniel Rodrigues
Daniel Rodrigues
Asked: 2010-08-09 13:49:14 +0800 CST2010-08-09 13:49:14 +0800 CST 2010-08-09 13:49:14 +0800 CST

如何在 shell 脚本中创建选择菜单?

  • 772

我正在创建一个简单的 bash 脚本,我想在其中创建一个选择菜单,如下所示:

$./script

echo "Choose your option:"

1) Option 1  
2) Option 2  
3) Option 3  
4) Quit  

并且根据用户的选择,我希望执行不同的操作。我是一个 bash shell 脚本新手,我在网上搜索了一些答案,但没有得到任何具体的答案。

scripts command-line bash
  • 12 12 个回答
  • 658247 Views

12 个回答

  • Voted
  1. Dennis Williamson
    2010-08-09T15:41:23+08:002010-08-09T15:41:23+08:00
    #!/bin/bash
    # Bash Menu Script Example
    
    PS3='Please enter your choice: '
    options=("Option 1" "Option 2" "Option 3" "Quit")
    select opt in "${options[@]}"
    do
        case $opt in
            "Option 1")
                echo "you chose choice 1"
                ;;
            "Option 2")
                echo "you chose choice 2"
                ;;
            "Option 3")
                echo "you chose choice $REPLY which is $opt"
                ;;
            "Quit")
                break
                ;;
            *) echo "invalid option $REPLY";;
        esac
    done
    

    在需要退出循环的任何地方添加break语句。select如果break不执行 a,则select语句循环并重新显示菜单。

    在第三个选项中,我包含了由select语句设置的变量,以证明您可以访问这些值。如果选择它,它将输出:

    you chose choice 3 which is Option 3
    

    您可以看到它$REPLY包含您在提示符处输入的字符串。它用作数组的索引,${options[@]}就好像数组是基于 1 的一样。该变量$opt包含数组中该索引的字符串。

    请注意,选择可以是直接在select语句中的简单列表,如下所示:

    select opt in foo bar baz 'multi word choice'
    

    但是您不能将这样的列表放入标量变量中,因为其中一个选项中有空格。

    如果您在文件中进行选择,您还可以使用文件通配符:

    select file in *.tar.gz
    
    • 224
  2. Alaa Ali
    2015-08-27T11:33:06+08:002015-08-27T11:33:06+08:00

    使用dialog,命令将如下所示:

    dialog --clear --backtitle "Backtitle here" --title "Title here" --menu "选择以下选项之一:" 15 40 4 \
    1“选项 1”\
    2“选项 2”\
    3“选项3”
    

    在此处输入图像描述

    将其放入脚本中:

    #!/bin/bash
    
    HEIGHT=15
    WIDTH=40
    CHOICE_HEIGHT=4
    BACKTITLE="Backtitle here"
    TITLE="Title here"
    MENU="Choose one of the following options:"
    
    OPTIONS=(1 "Option 1"
             2 "Option 2"
             3 "Option 3")
    
    CHOICE=$(dialog --clear \
                    --backtitle "$BACKTITLE" \
                    --title "$TITLE" \
                    --menu "$MENU" \
                    $HEIGHT $WIDTH $CHOICE_HEIGHT \
                    "${OPTIONS[@]}" \
                    2>&1 >/dev/tty)
    
    clear
    case $CHOICE in
            1)
                echo "You chose Option 1"
                ;;
            2)
                echo "You chose Option 2"
                ;;
            3)
                echo "You chose Option 3"
                ;;
    esac
    
    • 100
  3. MestreLion
    2011-08-05T23:40:11+08:002011-08-05T23:40:11+08:00

    本身并不是一个新的答案,但由于还没有公认的答案,这里有一些编码提示和技巧,适用于 select 和 zenity:

    title="Select example"
    prompt="Pick an option:"
    options=("A" "B" "C")
    
    echo "$title"
    PS3="$prompt "
    select opt in "${options[@]}" "Quit"; do 
        case "$REPLY" in
        1) echo "You picked $opt which is option 1";;
        2) echo "You picked $opt which is option 2";;
        3) echo "You picked $opt which is option 3";;
        $((${#options[@]}+1))) echo "Goodbye!"; break;;
        *) echo "Invalid option. Try another one.";continue;;
        esac
    done
    
    while opt=$(zenity --title="$title" --text="$prompt" --list \
                       --column="Options" "${options[@]}")
    do
        case "$opt" in
        "${options[0]}") zenity --info --text="You picked $opt, option 1";;
        "${options[1]}") zenity --info --text="You picked $opt, option 2";;
        "${options[2]}") zenity --info --text="You picked $opt, option 3";;
        *) zenity --error --text="Invalid option. Try another one.";;
        esac
    done
    

    值得一提:

    • 两者都会循环,直到用户明确选择退出(或取消 zenity)。这是交互式脚本菜单的好方法:选择一个选项并执行操作后,再次显示菜单以供另一个选择。如果选择是一次性的,那么就break在之后使用esac(zenity 方法也可以进一步减少)

    • 两者case都是基于索引的,而不是基于价值的。我认为这更容易编码和维护

    • 数组也用于zenity方法。

    • “退出”选项不在最初的原始选项中。它在需要时“添加”,因此您的阵列保持清洁。毕竟zenity不需要“退出”,用户只需点击“取消”(或关闭窗口)即可退出。请注意两者如何使用相同的、未触及的选项数组。

    • PS3并且REPLYvars不能重命名。select被硬编码以使用这些。脚本中的所有其他变量(opt、options、prompt、title)可以有任何你想要的名字,只要你做了调整

    • 71
  4. jibin
    2011-08-12T04:11:34+08:002011-08-12T04:11:34+08:00

    您可以使用这个简单的脚本来创建选项

    #!/bin/bash
    echo "选择操作************"
    回显“1)操作1”
    回显“2)操作2”
    echo "3) 操作 3"
    echo "4) 操作 4"
    读 案例 $n 在 1) echo "你选择了选项1";; 2) echo "你选择了选项 2";; 3) echo "你选择了选项 3";; 4) echo "你选择了选项 4";; *) echo "无效选​​项";; 经社理事会

    • 21
  5. HarlemSquirrel
    2015-05-17T19:58:39+08:002015-05-17T19:58:39+08:00

    我还有一个选项是这些答案的混合,但它的好处是你只需要按一个键,然后脚本就会继续,这要归功于-nread 选项。在此示例中,我们提示关闭、重新启动或简单地使用ANS我们的变量退出脚本,用户只需按 E、R 或 S。我还将默认设置为退出,因此如果按 Enter,则脚本将退出。

    #!/bin/bash
    read -n 1 -p "Would you like to exit, reboot, or shutdown? (E/r/s) " ans;
    
    case $ans in
        r|R)
            sudo reboot;;
        s|S)
            sudo poweroff;;
        *)
            exit;;
    esac
    
    • 17
  6. Alex Lucard
    2013-02-19T06:29:51+08:002013-02-19T06:29:51+08:00
    #!/bin/sh
    显示菜单(){
        正常=`回声“\033[米”`
        menu=`echo "\033[36m"` #Blue
        number=`echo "\033[33m"` #yellow
        bgred=`echo "\033[41m"`
        fgred=`echo "\033[31m"`
        printf "\n${菜单}****************************************** ***${正常}\n"
        printf "${menu}**${number} 1)${menu} 挂载保管箱 ${normal}\n"
        printf "${menu}**${number} 2)${menu} 挂载 USB 500 Gig Drive ${normal}\n"
        printf "${menu}**${number} 3)${menu} 重启 Apache ${normal}\n"
        printf "${menu}**${number} 4)${menu} ssh Frost TomCat 服务器 ${normal}\n"
        printf "${menu}**${number} 5)${menu} 其他一些命令${normal}\n"
        printf "${menu}************************************************ *${正常}\n"
        printf "请输入菜单选项并输入或 ${fgred}x 退出。${normal}"
        阅读选择
    }
    
    option_picked(){
        msgcolor=`echo "\033[01;31m"` # 粗体红色
        normal=`echo "\033[00;00m"` # 普通白色
        message=${@:-"${normal}错误:没有消息传递"}
        printf "${msgcolor}${消息}${正常}\n"
    }
    
    清除
    显示菜单
    而 [ $opt != '' ]
        做
        如果 [ $opt = '' ]; 然后
          出口;
        别的
          案例$选择加入
            1) 清晰;
                option_picked "选择了选项 1";
                printf "sudo mount /dev/sdh1 /mnt/DropBox/; #3 TB";
                显示菜单;
            ;;
            2) 清晰;
                option_picked "选择了选项 2";
                printf "sudo mount /dev/sdi1 /mnt/usbDrive; #500 gig 驱动器";
                显示菜单;
            ;;
            3) 清晰;
                option_picked "选择了选项 3";
                printf "sudo 服务 apache2 重启";
                显示菜单;
            ;;
            4) 清晰;
                option_picked "选择了选项 4";
                printf "ssh lmesser@ -p 2010";
                显示菜单;
            ;;
            x) 退出;
            ;;
            \n) 退出;
            ;;
            *)清除;
                option_picked "从菜单中选择一个选项";
                显示菜单;
            ;;
          经社理事会
        菲
    完毕
    • 10
  7. Li Lo
    2010-08-10T16:30:49+08:002010-08-10T16:30:49+08:00

    由于这是针对 Ubuntu,您应该使用配置为使用的任何后端 debconf。您可以通过以下方式找到 debconf 后端:

    sudo -s "echo get debconf/frontend | debconf-communicate"
    

    如果它说“对话框”,那么它可能使用whiptailor dialog。在 Lucid 上是whiptail.

    如果失败,请按照 Dennis Williamson 的说明使用 bash “select”。

    • 7
  8. user360154
    2014-12-20T01:15:25+08:002014-12-20T01:15:25+08:00

    Bash 精美菜单

    先尝试一下,然后访问我的页面以获取详细说明...无需外部库或程序,例如 dialog 或 zenity ...

    #/bin/bash
    # by oToGamez
    # www.pro-toolz.net
    
          E='echo -e';e='echo -en';trap "R;exit" 2
        ESC=$( $e "\e")
       TPUT(){ $e "\e[${1};${2}H";}
      CLEAR(){ $e "\ec";}
      CIVIS(){ $e "\e[?25l";}
       DRAW(){ $e "\e%@\e(0";}
      WRITE(){ $e "\e(B";}
       MARK(){ $e "\e[7m";}
     UNMARK(){ $e "\e[27m";}
          R(){ CLEAR ;stty sane;$e "\ec\e[37;44m\e[J";};
       HEAD(){ DRAW
               for each in $(seq 1 13);do
               $E "   x                                          x"
               done
               WRITE;MARK;TPUT 1 5
               $E "BASH SELECTION MENU                       ";UNMARK;}
               i=0; CLEAR; CIVIS;NULL=/dev/null
       FOOT(){ MARK;TPUT 13 5
               printf "ENTER - SELECT,NEXT                       ";UNMARK;}
      ARROW(){ read -s -n3 key 2>/dev/null >&2
               if [[ $key = $ESC[A ]];then echo up;fi
               if [[ $key = $ESC[B ]];then echo dn;fi;}
         M0(){ TPUT  4 20; $e "Login info";}
         M1(){ TPUT  5 20; $e "Network";}
         M2(){ TPUT  6 20; $e "Disk";}
         M3(){ TPUT  7 20; $e "Routing";}
         M4(){ TPUT  8 20; $e "Time";}
         M5(){ TPUT  9 20; $e "ABOUT  ";}
         M6(){ TPUT 10 20; $e "EXIT   ";}
          LM=6
       MENU(){ for each in $(seq 0 $LM);do M${each};done;}
        POS(){ if [[ $cur == up ]];then ((i--));fi
               if [[ $cur == dn ]];then ((i++));fi
               if [[ $i -lt 0   ]];then i=$LM;fi
               if [[ $i -gt $LM ]];then i=0;fi;}
    REFRESH(){ after=$((i+1)); before=$((i-1))
               if [[ $before -lt 0  ]];then before=$LM;fi
               if [[ $after -gt $LM ]];then after=0;fi
               if [[ $j -lt $i      ]];then UNMARK;M$before;else UNMARK;M$after;fi
               if [[ $after -eq 0 ]] || [ $before -eq $LM ];then
               UNMARK; M$before; M$after;fi;j=$i;UNMARK;M$before;M$after;}
       INIT(){ R;HEAD;FOOT;MENU;}
         SC(){ REFRESH;MARK;$S;$b;cur=`ARROW`;}
         ES(){ MARK;$e "ENTER = main menu ";$b;read;INIT;};INIT
      while [[ "$O" != " " ]]; do case $i in
            0) S=M0;SC;if [[ $cur == "" ]];then R;$e "\n$(w        )\n";ES;fi;;
            1) S=M1;SC;if [[ $cur == "" ]];then R;$e "\n$(ifconfig )\n";ES;fi;;
            2) S=M2;SC;if [[ $cur == "" ]];then R;$e "\n$(df -h    )\n";ES;fi;;
            3) S=M3;SC;if [[ $cur == "" ]];then R;$e "\n$(route -n )\n";ES;fi;;
            4) S=M4;SC;if [[ $cur == "" ]];then R;$e "\n$(date     )\n";ES;fi;;
            5) S=M5;SC;if [[ $cur == "" ]];then R;$e "\n$($e by oTo)\n";ES;fi;;
            6) S=M6;SC;if [[ $cur == "" ]];then R;exit 0;fi;;
     esac;POS;done
    
    • 7
  9. LazyEchidna
    2011-05-05T17:28:41+08:002011-05-05T17:28:41+08:00

    我使用过 Zenity,它在 Ubuntu 中似乎一直存在,运行良好并且有很多功能。这是一个可能的菜单的草图:

    #! /bin/bash
    
    selection=$(zenity --list "Option 1" "Option 2" "Option 3" --column="" --text="Text above column(s)" --title="My menu")
    
    case "$selection" in
    "Option 1")zenity --info --text="Do something here for No1";;
    "Option 2")zenity --info --text="Do something here for No2";;
    "Option 3")zenity --info --text="Do something here for No3";;
    esac
    
    • 6
  10. txwikinger
    2010-08-09T13:56:10+08:002010-08-09T13:56:10+08:00

    serverfault已经回答了同样的问题。那里的解决方案使用whiptail。

    • 3

相关问题

  • 如何从命令行仅安装安全更新?关于如何管理更新的一些提示

  • 如何从命令行刻录双层 dvd iso

  • 如何从命令行判断机器是否需要重新启动?

  • 文件权限如何工作?文件权限用户和组

  • 如何在 Vim 中启用全彩支持?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何安装 .run 文件?

    • 7 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    如何获得 CPU 温度?

    • 21 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Marko Smith

    如何使用命令行将用户添加为新的 sudoer?

    • 7 个回答
  • Marko Smith

    更改文件夹权限和所有权

    • 9 个回答
  • Marko Smith

    你如何重新启动Apache?

    • 13 个回答
  • Marko Smith

    如何卸载软件?

    • 11 个回答
  • Marko Smith

    如何删除 PPA?

    • 26 个回答
  • Martin Hope
    NES 如何启用或禁用服务? 2010-12-30 13:03:32 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    Olivier Lalonde 如何在结束 ssh 会话后保持进程运行? 2010-10-22 04:09:13 +0800 CST
  • Martin Hope
    David B 如何使用命令行将用户添加为新的 sudoer? 2010-10-16 04:02:45 +0800 CST
  • Martin Hope
    Hans 如何删除旧内核版本以清理启动菜单? 2010-08-21 19:37:01 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve