it-swarm.cn

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

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

$./script

echo "Choose your option:"

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

根据用户的选择,我希望执行不同的操作。我是一个bash Shell脚本菜鸟,我在网上搜索了一些答案,但没有真正具体。

129
Daniel Rodrigues
#!/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,则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
147
Dennis Williamson

不是一个新的答案本身,但由于还没有接受的答案,这里有一些编码提示和技巧,对于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 $REPLY";;
    2 ) echo "You picked $opt which is option $REPLY";;
    3 ) echo "You picked $opt which is option $REPLY";;

    $(( ${#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都不需要“退出”,用户只需单击“取消”(或关闭窗口)即可退出。 请注意两者是如何使用相同的,未触及的选项数组。

  • PS3REPLY变量可以重命名。 select被硬编码以使用它们。如果您进行调整,脚本中的所有其他变量(opt,options,Prompt,title)可以包含您想要的任何名称

56
MestreLion

使用 dialog ,命令如下所示:

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

enter image description here

将它放在脚本中:

#!/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
54
Alaa Ali

您可以使用此简单脚本来创建选项

#!/ bin/bash 
 echo“选择操作************”
 echo“1)操作1”
 echo“2)操作2“
 echo”3)操作3“
 echo”4)操作4“ 
在 中读n 案例$ n 1)echo“你选择了选项1”;; 2)echo“你选择了选项2”;; 3)回声“你选择了选项3”;; 4)回声“你选择了选项4”;; *)回声“无效选项”;; esac
14
jibin

我还有一个选项是这些答案的混合,但是它的好处是你只需要按一个键然后由于-n选项的读取而继续脚本。在这个例子中,我们提示关闭,重新启动或者只是使用ANS作为我们的变量退出脚本,用户只需要按E,R或S.我还将默认值设置为exit,这样如果按下enter,那么脚本将退出。

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
8
HarlemSquirrel

由于这是针对Ubuntu的,因此您应该使用debconf配置使用的任何后端。你可以找到debconf后端:

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

如果它显示“对话框”,那么它可能使用whiptaildialog。在Lucid上它是whiptail

如果失败,请按照丹尼斯威廉姆森的解释使用bash“select”。

7
Li Lo
#!/ bin/sh 
 show_menu(){[。_____。] normal =`echo“\ 033 [m”`
 menu =`echo“\ 033 [36m”`#Blue 
 number =`echo“\ 033 [33m”`#yellow 
 bgred =`echo“\ 033 [41m”`
 fgred =`echo“\ 033 [31m”`
 printf“\ n $ {menu} ************************************** ******* $ {normal}\n“
 printf”$ {menu} ** $ {number} 1)$ {menu}挂载dropbox $ {normal}\n“
 printf“$ {menu} ** $ {number} 2)$ {menu}挂载USB 500 Gig Drive $ {普通}\n”
 printf“$ {menu} ** $ {number} 3) $ {menu}重新启动Apache $ {normal}\n“
 printf”$ {menu} ** $ {number} 4)$ {menu} ssh Frost Tomcat Server $ {normal}\n“
 printf“$ {menu} ** $ {number} 5)$ {menu}其他一些命令$ {normal}\n”
 printf“$ {menu} ********* ************************************ $ {normal}\n“
 printf”请输入菜单选项并输入或$ {fgred} x退出。$ {normal}“
 read opt 
} 
 
 option_picked(){
 msgcolor =`echo“\ 033 [01; 31m”`#bold red 
 normal =`echo“\ 033 [00; 00m”`#normal white 
 message = $ {@: - “$ {normal}错误:没有消息传递”} 
 printf“$ {msgcolor } $ {message} $ {normal}\n“
} 
 
 clear 
 show_menu 
而[$ opt!=''] 
 
如果[$ opt =''];然后
退出; 
否则
案例$ opt in 
 1)clear; 
 option_picked“Option 1 Picked”; 
 printf “Sudo mount/dev/sdh1/mnt/DropBox /; #The 3 TB”; 
 show_menu; 
 ;; 
 2)clear; 
 option_picked“Option 2挑选“; 
 printf”Sudo mount/dev/sdi1/mnt/usbDrive; #The 500 gig drive“; 
 show_menu; 
 ;; 
 3) clear; 
 option_picked“Option 3 Picked”; 
 printf“Sudo service Apache2 restart”; 
 show_menu; 
 ;; 
 4)clear; 
 option_picked“Option 4 Picked”; 
 printf“ssh lmesser @ -p 2010”; 
 show_menu; 
 ;; 
 x)退出; 
 ;; 
\n)退出; 
 ;; 
 *)清楚; 
 option_picked“从中选择一个选项菜单“; 
 show_menu; 
 ;; 
 esac 
 fi 
已完成
7
Alex Lucard

我使用了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
LazyEchidna

Bash花式菜单

首先尝试一下,然后访问我的页面进行详细描述......不需要外部库或对话或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
5
user360154

serverfault 回答中已经存在相同的问题。那里的解决方案使用 whiptail

2
txwikinger