it-swarm-pt.tech

Como posso criar um menu de seleção em um script de shell?

Estou criando um script bash simples e quero criar um menu de seleção, assim:

$./script

echo "Choose your option:"

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

E de acordo com a escolha do usuário, quero que ações diferentes sejam executadas. Eu sou um noob script shell da Shell, eu procurei na web por algumas respostas, mas não consegui nada realmente concreto.

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

Adicione instruções break sempre que precisar do loop select para sair. Se um break não for executado, a instrução select entrará em loop e o menu será exibido novamente.

Na terceira opção, incluí variáveis ​​que são definidas pela instrução select para demonstrar que você tem acesso a esses valores. Se você escolher, irá gerar:

you chose choice 3 which is Option 3

Você pode ver que $REPLY contém a string digitada no prompt. É usado como um índice no array ${options[@]} como se o array fosse baseado em 1. A variável $opt contém a string desse índice na matriz.

Observe que as opções podem ser uma lista simples diretamente na instrução select, desta forma:

select opt in foo bar baz 'multi Word choice'

mas você não pode colocar essa lista em uma variável escalar por causa dos espaços em uma das opções.

Você também pode usar o globbing de arquivos se estiver escolhendo entre arquivos:

select file in *.tar.gz
137
Dennis Williamson

Não é uma nova resposta per se, mas como não há nenhuma resposta aceita ainda, aqui estão algumas dicas e truques de codificação, tanto para seleção quanto para 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

Vale a pena mencionar:

  • Ambos irão fazer um loop até que o usuário escolha explicitamente Sair (ou Cancelar para zenidade). Essa é uma boa abordagem para menus de script interativos: depois que uma opção é selecionada e a ação executada, o menu é apresentado novamente para outra escolha. Se a escolha for apenas uma vez, use break após esac (a abordagem zenity também pode ser reduzida)

  • Ambos case são baseados em índice, em vez de baseados em valor. Eu acho que isso é mais fácil de codificar e manter

  • Array também é usado para a abordagem zenity.

  • A opção "Sair" não está entre as opções iniciais e originais. É "adicionado" quando necessário, para que sua matriz fique limpa. Afinal, "Quit" não é necessário para zenity de qualquer maneira, o usuário pode simplesmente clicar em "Cancelar" (ou fechar a janela) para sair. Observe como ambos usam o mesmo array intocado de opções.

  • PS3 e REPLY vars podem not ser renomeados. select é codificado para usá-los. Todas as outras variáveis ​​no script (opt, options, Prompt, title) podem ter qualquer nome desejado, desde que você faça os ajustes

54
MestreLion

Usando dialog , o comando ficaria assim:

dialog --clear --backtitle "Backtitle here" --título "Title here" --menu "Escolha uma das seguintes opções:" 15 40 4\
 1 "Opção 1"\
 2 "Opção 2"\
 3 "Opção 3" 

enter image description here

Colocando em um 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

Você pode usar este script simples para criar opções

#!/bin/bash 
 echo "selecione a operação ************" 
 echo "1) operação 1" 
 echo "2) operação 2 "
 echo" 3) operação 3 "
 echo" 4) operação 4 " 
leia n caso $ n em 1) echo "Você escolheu a Opção 1" ;; 2) echo "Você escolheu a Opção 2" ;; 3) echo "Você escolheu a Opção 3" ;; 4) echo "Você escolheu a Opção 4" ;; *) Echo "opção inválida" ;; Esac
14
jibin

Uma vez que isto é direccionado para o Ubuntu, deve usar o debend de backend que está configurado para usar. Você pode descobrir o backend do debconf com:

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

Se ele diz "diálogo", então provavelmente usa whiptail ou dialog. No Lucid é whiptail.

Se isso falhar, use bash "select" como explicado por Dennis Williamson.

7
Li Lo
#!/bin/sh 
 show_menu () {
 normal = echo "\ 033 [m" `
 menu = echo"\033 [36m "` #Blue 
 número = `echo"\033 [33m "` # amarelo 
 bgred = `echo"\033 [41m "` 
 fgred = `echo"\033 [31m "` 
 printf "\ n $ {menu} ************************************** ******* $ {normal}\n "
 printf" $ {menu} ** $ {number} 1) $ {menu} Monte a caixa de depósito $ {normal}\n "
 printf "$ {menu} ** $ {number} 2) $ {menu} Montar 500 Gig Drive USB $ {normal}\n" 
 printf "$ {menu} ** $ {número} 3) $ {menu} Reinicie o Apache $ {normal}\n "
 printf" $ {menu} ** $ {número} 4) $ {menu} ssh Servidor Frost Tomcat $ {normal}\n "
 printf "$ {menu} ** $ {number} 5) $ {menu} Alguns outros comandos $ {normal}\n" 
 printf "$ {menu} ********* ************************************ $ {normal}\n "
 printf" Por favor, insira uma opção de menu e digite ou $ {fgred} x para sair. $ {Normal} "
 Leia opt 
} 
 
 Option_picked () {
 msgcolor = `echo"\033 [01; 31m "` # negrito vermelho 
 normal = `echo"\033 [00; 00m "` # normal branco 
 message = $ {@: - "$ {normal} Erro: nenhuma mensagem foi passada"} 
 printf "$ {msgcolor } $ {message} $ {normal}\n "
} 
 
 claro 
 show_menu 
 enquanto [$ opt! = ''] 
 do 
 if [$ opt = '']; então 
 exit; 
 else 
 case $ opt in 
 1) claro; 
 option_picked "Opção 1 escolhida"; 
 printf "Sudo mount/dev/sdh1/mnt/DropBox /; #O 3 terabyte"; 
 Show_menu; 
 ;; 
 2) claro; 
 Option_picked "Opção 2 Escolhido "; 
 Printf" Sudo mount/dev/sdi1/mnt/usbDrive; #O drive de 500 gig "; 
 Show_menu; 
 ;; 
 3) clear; 
 option_picked "Opção 3 Escolhida"; 
 printf "Serviço Sudo Apache2 restart"; 
 show_menu; 
 ;; 
 4) limpar; 
 option_picked "Opção 4 escolhida"; 
 printf "ssh lmesser @ -p 2010"; 
 show_menu; 
 ;; 
 x) exit; 
 ;; 
\n) exit; 
 ;; 
 *) claro; 
 option_picked "Escolha uma opção de o menu "; 
 show_menu; 
 ;; 
 esac 
 fi 
 feito
7
Alex Lucard

Eu tenho mais uma opção que é uma mistura dessas respostas, mas o que torna isso legal é que você só precisa pressionar uma tecla e depois o script continua graças à opção -n de leitura. Neste exemplo, estamos solicitando o desligamento, reinicialização ou simplesmente sair do script usando ANS como nossa variável e o usuário só precisa pressionar E, R ou S. Eu também configuro o padrão para sair, então se enter for pressionado, o script sairá.

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

Eu usei o Zenity, que sempre aparece no Ubuntu, funciona muito bem e tem muitos recursos. Este é um esboço de um possível menu:

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

Experimente primeiro, depois visite minha página para descrição detalhada ... Não há necessidade de bibliotecas externas ou programas como diálogo 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

Já existe a mesma questão em serverfault respondida. A solução lá usa whiptail .

2
txwikinger