Utilisation de la commande `select` pour imprimer un menu dans Bash

10

J'essaye d'implémenter un menu simple en utilisant la selectcommande. Le script (à des fins de test) est le suivant:

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

Le script ne reconnaît aucune entrée valide que je donne et affiche toujours le message "option non valide". Que fais-je de mal dans ce script?

Sumod
la source
4
Votre entrée est 1, 2 ou 3, non?
enzotib

Réponses:

11

Votre menu affiché par select ressemblera à:

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

A ce moment, vous entrez "1" ou "2" ou "3": vous ne tapez pas le mot.

En outre, selectboucle jusqu'à ce qu'il voit une breakcommande, vous voulez donc ceci:

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

Si vous vouliez autoriser l'utilisateur à saisir le nombre ou le mot, vous pourriez écrire ceci:

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 virgule n'a aucune signification syntaxique, elle est juste là pour pouvoir faire correspondre les motifs sur la variable $ REPLY (qui est ce que l'utilisateur a réellement tapé) ou la variable $ opt

glenn jackman
la source
La selectcommande a besoin d'un break, non case.
glenn jackman
Merci! Je ne savais pas que c'était des options numériques. Duhh!
Sumod
Hah, moi aussi je programme en C et vous en avez besoin breakdans chaque section. Cependant, vous ne serez jamais besoin d' un breakdans un cas ... esac bloc dans un script shell . Il peut arriver si facilement de les mélanger. :-)
erreur de syntaxe
1
@syntaxerror, vous avez raison, vous n'avez pas besoin breakpour case. Cependant, vous avez besoin d'un breakpour échapper à la selectboucle.
glenn jackman
@glenn jackman J'aimerais que cela devienne un commentaire plus utile (voir ci-dessous). Ce serait donc formidable si vous conveniez de supprimer votre commentaire de 12h55. Je ferai de même avec le mien, bien sûr.
erreur de syntaxe
3

Votre $optvariable sera définie sur le mot d'option correspondant au nombre saisi par l'utilisateur. Si vous voulez regarder ce que l'utilisateur a réellement tapé, regardez $REPLY.

Kusalananda
la source
1
Étant donné que le casecompare $optà "apache", "nommé" et "sendmail", il est correct et rien ne doit être changé.
manatwork
@manatwork, sauf si l'OP veut que l'utilisateur tape les mots "apache", "named" ou "sendmail" plutôt que d'appuyer sur 1, 2 ou 3.
Kusalananda
Intéressant. $ REPLY détient 1/ 2/ 3, et $ opt détient apache/ named/sendmail
Peter.O
@fred, oui, $REPLYest tout ce que l'utilisateur a tapé, et s'il s'agissait d'un numéro valide, ce $optsera le mot correspondant à ce numéro.
Kusalananda