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?

Sumod
fonte
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

Glenn Jackman
fonte
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.

Kusalananda
fonte
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