web-dev-qa-db-fra.com

Comment créer un menu de sélection dans un script shell?

Je crée un script bash simple et je veux y créer un menu de sélection, comme ceci:

$./script

echo "Choose your option:"

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

Et selon le choix de l'utilisateur, je souhaite que différentes actions soient exécutées. Je suis un scripteur de scripts bash Shell, j'ai cherché sur le Web des réponses, mais je n'ai rien de concret.

122
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

Ajoutez des instructions break chaque fois que vous avez besoin de la boucle select pour quitter. Si un break n'est pas exécuté, l'instruction select est bouclée et le menu est affiché à nouveau.

Dans la troisième option, j'ai inclus les variables définies par l'instruction select afin de démontrer que vous avez accès à ces valeurs. Si vous le choisissez, il générera:

you chose choice 3 which is Option 3

Vous pouvez constater que $REPLY contient la chaîne que vous avez entrée à l'invite. Il est utilisé comme index dans le tableau ${options[@]} comme si le tableau était basé sur 1. La variable $opt contient la chaîne de cet index dans le tableau.

Notez que les choix peuvent être une simple liste directement dans l'instruction select, comme ceci:

select opt in foo bar baz 'multi Word choice'

mais vous ne pouvez pas mettre une telle liste dans une variable scalaire à cause des espaces dans l'un des choix.

Vous pouvez également utiliser la suppression de fichier si vous choisissez parmi les fichiers:

select file in *.tar.gz
137
Dennis Williamson

Pas une nouvelle réponse en soi, mais comme il n'y a pas encore de réponse acceptée, voici quelques astuces et astuces de codage, à la fois pour select et 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

À noter:

  • Les deux vont être en boucle jusqu'à ce que l'utilisateur choisisse explicitement de quitter (ou Annuler pour zenity). C'est une bonne approche pour les menus de script interactifs: après avoir sélectionné un choix et effectué l'action, le menu est présenté à nouveau pour un autre choix. Si choix est censé être unique, utilisez simplement breakaprès esac(l’approche de zenity pourrait être davantage réduite également)

  • casesont tous deux basés sur l'index plutôt que sur la valeur. Je pense que c'est plus facile à coder et à maintenir

  • Le tableau est également utilisé pour l'approche zenityname__.

  • L'option "Quitter" ne figure pas parmi les options initiales d'origine. Il est "ajouté" si nécessaire, afin que votre tableau reste propre. Après tout, "Quitter" n'est de toute façon pas nécessaire pour zenity, l'utilisateur peut simplement cliquer sur "Annuler" (ou fermer la fenêtre) pour quitter. Remarquez comment les deux utilisent le même tableau d'options intact.

  • PS3 et REPLYvars peuvent ne pas être renommés. selectest codé en dur pour les utiliser. Toutes les autres variables du script (opt, options, Prompt, title) peuvent avoir les noms de votre choix, à condition de faire les ajustements.

54
MestreLion

En utilisant dialog , la commande ressemblerait à ceci:

dialogue --clear --backtitle "Backtitle here" --title "Title here" --menu "Choisissez l'une des options suivantes:" 15 40 4\
 1 "Option 1"\
 2 "Option 2"\
 3 "Option 3" 

enter image description here

En le mettant dans un script:

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

Vous pouvez utiliser ce script simple pour créer des options

#!/bin/bash 
 echo "sélectionne l'opération ************" 
 echo "1) opération 1" 
 echo "2) opération 2 "
 écho" 3) opération 3 "
 écho" 4) opération 4 " 
read n case $ n in 1) echo "Vous avez choisi l'option 1" ;; 2) echo "Vous avez choisi l'option 2" ;; ____.] 3) echo "Vous avez choisi l'option 3" ;; 4) echo "Vous avez choisi l'option 4" ;; *) Echo "option invalide" ;; Esac
14
jibin

Etant donné que ceci est destiné à Ubuntu, vous devez utiliser le backend que debconf est configuré pour utiliser. Vous pouvez trouver le backend de debconf avec:

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

S'il indique "dialogue", il utilisera probablement whiptailou dialogname__. Sur Lucid, c'est whiptailname__.

Si cela échoue, utilisez bash "select" comme expliqué par Dennis Williamson.

7
Li Lo
#!/bin/sh 
 show_menu () {
 normal = `echo"\033 [m "` 
 menu = `echo"\033 [36m "` #Bleu 
 nombre = `echo"\033 [33m "` #yellow 
 bgred = `echo"\033 [41m "` 
 fgred = "echo"\033 [31m "` 
 printf "\ n $ {menu} ************************************* ******* $ {normal}\n "
 printf" $ {menu} ** $ {numéro} 1) $ {menu} Monter la boîte déroulante $ {normal}\n "
 printf "$ {menu} ** $ {numéro} 2) $ {menu} Monter un lecteur USB 500 Go $ {normal}\n" 
 printf "$ {menu} ** $ {numéro} 3) $ {menu} Redémarrez Apache $ {normal}\n "
 printf" $ {menu} ** $ {numéro} 4) $ {menu} ssh Frost Tomcat Server $ {normal}\n "
 printf "$ {menu} ** $ {numéro} 5) $ {menu} Quelques autres commandes $ {normal}\n" 
 printf "$ {menu} ********* ************************************ $ {normal}\n "
 printf" Veuillez entrer une option de menu et entrez ou $ {fgred} x pour quitter. $ {Normal} "
 Read opt 
} 
 
 Option_picked () {
 msgcolor = `echo"\033 [01; 31m "` # gras rouge 
 normal = `echo"\033 [00; 00m "` # blanc normal 
 message = $ {@: - "$ {normal} Erreur: aucun message n'a été transmis"} 
 printf "$ {msgcolor } $ {message} $ {normal}\n "
} 
 
 effacer 
 show_menu 
 tant que [$ opt! = ''] 
 faire 
 si [$ opt = '']; puis 
 sortie; 
 autre 
 cas $ opter pour 
 1) effacer; 
 sélectionné par "Option 1 choisie"; 
 printf "Sudo mount/dev/sdh1/mnt/DropBox /; #The 3 terabyte"; 
 Show_menu; 
 ;; 
 2) effacer; 
 Option_picked "Option 2 Choisi "; 
 Printf" Sudo mount/dev/sdi1/mnt/usbDrive; #Le lecteur 500 Go "; 
 Show_menu; 
 ;; 
 3) clear; 
 option_picked "Option 3 sélectionnée"; 
 printf "Sudo service Apache2 restart"; 
 show_menu; 
 ;; 
 4) effacer; 
 option_picked "Option 4 Picked"; 
 printf "ssh lmesser @ -p 2010"; 
 show_menu; 
 ;; 
 x) quitter; 
 ;; 
\n) exit; 
 ;; 
 *) clear; 
 option_picked "Choisissez une option dans le menu "; 
 show_menu; 
 ;; 
 esac 
 fi 
 terminé
7
Alex Lucard

J'ai une autre option qui est un mélange de ces réponses, mais ce qui la rend agréable c'est qu'il suffit d'appuyer sur une touche, puis le script se poursuit grâce à l'option -n de lecture. Dans cet exemple, nous vous invitons à arrêter, à redémarrer ou simplement à quitter le script en utilisant ANS comme variable et l'utilisateur doit uniquement appuyer sur E, R ou S. La valeur par défaut est Quitter. Par conséquent, si vous appuyez sur Entrée, la commande le script va sortir.

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

J'ai utilisé Zenity, qui semble toujours être présent dans Ubuntu, fonctionne très bien et dispose de nombreuses fonctionnalités. Ceci est un croquis d'un menu possible:

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

Menu fantaisie Bash

Essayez-le d'abord, puis visitez ma page pour une description détaillée ... Pas besoin de bibliothèques externes ou de programmes comme dialog ou 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

Il y a déjà la même question dans serverfault répondu. La solution utilise ici whiptail .

2
txwikinger