Usando il comando `select` per stampare un menu in Bash


10

Sto cercando di implementare un semplice menu usando il selectcomando. Lo script (a scopo di test) è il seguente:

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

Lo script non riconosce alcun input valido che do e stampa sempre il messaggio "opzione non valida". Cosa sto facendo di sbagliato in questo script?


4
Il tuo input è 1, 2 o 3, giusto?
enzotib,

Risposte:


11

Il tuo menu mostrato da select apparirà come:

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

In questo momento, inserisci "1" o "2" o "3": non digiti la parola.

Inoltre, selecteseguirà il ciclo fino a quando non vede un breakcomando, quindi vuoi questo:

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

Se si desidera consentire all'utente di immettere il numero o la parola, è possibile scrivere questo:

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

La virgola non ha alcun significato sintattico, è lì solo per essere in grado di modellare la corrispondenza sulla variabile $ REPLY (che è ciò che l'utente ha effettivamente digitato) o sulla variabile $ opt


Il selectcomando richiede un break, no case.
Glenn Jackman,

Grazie! Non mi rendevo conto che si trattava di opzioni numeriche. Duhh!
Sumod,

Ah, anch'io programma in C e, hai bisogno di un breaklì in ogni sezione. Tuttavia, non si sarà mai bisogno di una breakin un caso ... esac blocco in uno script di shell . Può succedere così facilmente confonderli. :-)
syntaxerror

1
@syntaxerror, hai ragione, non è necessario breakper case. Tuttavia, è necessario un breakper sfuggire al selectciclo.
Glenn Jackman,

@glenn jackman Vorrei che questo si trasformasse in un commento più utile (vedi dopo). Quindi sarebbe fantastico se accetti di eliminare il tuo commento dalle 12:55. Farò lo stesso con il mio, ovviamente.
syntaxerror,

3

La $optvariabile verrà impostata sulla parola dell'opzione corrispondente al numero immesso dall'utente. Se vuoi vedere ciò che l'utente ha effettivamente digitato, guarda $REPLY.


1
Dato che il caseconfronto $optcon "apache", "nominato" e "sendmail", è corretto e nulla deve essere cambiato.
arte

@manatwork, a meno che l'OP non voglia che l'utente digiti le parole "apache", "nominato" o "sendmail" anziché premere 1, 2 o 3.
Kusalananda

Interessante. $ REPLY detiene 1/ 2/ 3e $ opt detiene apache/ named/sendmail
Peter.O

@fred, sì, $REPLYè qualunque cosa l'utente abbia digitato, e se fosse un numero valido allora $optsarà la parola corrispondente a quel numero.
Kusalananda
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.