Verwenden Sie den Befehl `select`, um ein Menü in Bash zu drucken

10

Ich versuche, ein einfaches Menü mit dem selectBefehl zu implementieren . Das Skript (zu Testzwecken) lautet wie folgt:

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

Das Skript erkennt keine gültigen Eingaben, die ich gebe, und gibt immer die Meldung "Ungültige Option" aus. Was mache ich in diesem Skript falsch?

Sumod
quelle
4
Ihre Eingabe ist 1, 2 oder 3, richtig?
Enzotib

Antworten:

11

Ihr von select angezeigtes Menü sieht folgendermaßen aus:

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

Zu diesem Zeitpunkt geben Sie "1" oder "2" oder "3" ein: Sie geben das Wort nicht ein.

Außerdem selectwird eine Schleife ausgeführt, bis ein breakBefehl angezeigt wird. Sie möchten also Folgendes:

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

Wenn Sie dem Benutzer erlauben möchten, entweder die Nummer oder das Wort einzugeben, können Sie Folgendes schreiben:

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

Das Komma hat keine syntaktische Bedeutung. Es dient lediglich dazu, die Musterübereinstimmung entweder für die Variable $ REPLY (die vom Benutzer tatsächlich eingegeben wurde) oder für die Variable $ opt zu erstellen

Glenn Jackman
quelle
Der selectBefehl braucht ein break, nicht case.
Glenn Jackman
Vielen Dank! Mir war nicht klar, dass es sich um numerische Optionen handelte. Duhh!
Sumod
Hah, ich programmiere auch in C und du brauchst breakdort in jedem Abschnitt ein. Allerdings werden Sie nie brauchen breakin einem Fall ... esac Block in einem Shell - Skript . Es kann so leicht passieren, dass sie durcheinander geraten. :-)
Syntaxfehler
1
@syntaxerror, sind Sie richtig, Sie brauchen nicht breakzu case. Sie benötigen jedoch eine break, um der selectSchleife zu entkommen .
Glenn Jackman
@glenn jackman Ich möchte, dass dies zu einem hilfreicheren Kommentar wird (siehe weiter unten). Es wäre also großartig, wenn Sie zustimmen würden, Ihren Kommentar von 12:55 zu löschen. Ich werde das natürlich auch mit meinen machen.
Syntaxfehler
3

Ihre $optVariable wird auf das Optionswort gesetzt, das der vom Benutzer eingegebenen Nummer entspricht . Wenn Sie sehen möchten, was der Benutzer tatsächlich eingegeben hat, schauen Sie sich an $REPLY.

Kusalananda
quelle
1
Angesichts der caseVergleiche $optmit "Apache", "Named" und "Sendmail" ist dies korrekt und es muss nichts geändert werden.
Manatwork
@manatwork, es sei denn, das OP möchte, dass der Benutzer die Wörter "apache", "named" oder "sendmail" eingibt, anstatt 1, 2 oder 3 zu drücken.
Kusalananda
Interessant. $ REPLY hält 1/ 2/ 3und $ opt hält apache/ named/sendmail
Peter.O
@fred, ja, $REPLYist das, was der Benutzer eingegeben hat, und wenn es eine gültige Nummer war, $optist dies das Wort, das dieser Nummer entspricht.
Kusalananda