Usando o comando `select` para imprimir um menu no Bash


10

Estou tentando implementar um menu simples usando o selectcomando O script (para fins de teste) é o seguinte:

#!/bin/bash
echo "*******************"
PS3='Select an option and press Enter: '
options=("apache" "named" "sendmail")
select opt in "${options[@]}"
do
  case $opt in
        "apache")
          date
          ;;
        "named")
          echo "test"
          ;;
        "sendmail")
          echo "test 2"
          ;;
        *) echo "invalid option";;
  esac
done
echo "*********************"

O script não reconhece nenhuma entrada válida fornecida e sempre imprime a mensagem "opção inválida". O que estou fazendo de errado neste script?


4
Sua entrada é 1, 2 ou 3, certo?
enzotib 14/09/11

Respostas:


11

Seu menu mostrado por select será parecido com:

1) apache
2) named
3) sendmail
Select an option and press Enter: 

Nesse momento, você insere "1" ou "2" ou "3": não digita a palavra.

Além disso, selectfará um loop até encontrar um breakcomando, então você deseja o seguinte:

  case $opt in
        "apache")
          date
          break
          ;;
        "named")
          echo "test"
          break
          ;;
        "sendmail")
          echo "test 2"
          break
          ;;
        *) echo "invalid option";;
  esac

Se você deseja permitir que o usuário digite o número ou a palavra, você pode escrever o seguinte:

select opt in "${options[@]}"; do
  case "$opt,$REPLY" in
    apache,*|*,apache)     do_something; break ;;
    named,*|*,named)       do_something; break ;;
    sendmail,*|*,sendmail) do_something; break ;;
  esac
done

A vírgula não tem significado sintático, apenas existe para poder padronizar a correspondência na variável $ REPLY (que é o que o usuário realmente digitou) ou na variável $ opt


O selectcomando precisa de um break, não case.
Glenn Jackman

Obrigado! Não percebi que eram opções numéricas. Duhh!
Sumod 15/09/11

Hah, eu também programa em C e, você precisa de um breaklá em todas as seções. No entanto, você nunca vai precisar de um breakem um caso ... esac bloco em um script shell . Isso pode acontecer tão facilmente para misturá-los. :-)
syntaxerror

11
@syntaxerror, você está certo, você não precisa breakpara case. No entanto, você precisa de um breakpara escapar do selectloop.
precisa

@ Jackman Jennifer Eu gostaria que isso se transformasse em um comentário mais útil (veja a seguir). Portanto, seria ótimo se você concordasse em excluir seu comentário das 12:55. Eu farei o mesmo com o meu, é claro.
Syntaxerror 23/11

3

Sua $optvariável será configurada para a palavra de opção correspondente ao número que o usuário digitar. Se você quiser ver o que o usuário realmente digitou, veja $REPLY.


11
Dado que o casecompara $optcom "apache", "nomeado" e "sendmail", está correto e nada precisa ser alterado.
manatwork 14/09/11

@manatwork, a menos que a OP quer o utilizador para digitar as palavras "Apache", "Nome" ou "sendmail" em vez de pressionar 1, 2 ou 3.
Kusalananda

Interessante. $ REPLY mantém 1/ 2/ 3, e $ opt mantém apache/ named/sendmail
Peter.O

@fred, sim, $REPLYé o que o usuário digitou e, se fosse um número válido, $optserá a palavra correspondente a esse número.
Kusalananda
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.