Za pomocą polecenia `select`, aby wydrukować menu w Bash

10

Próbuję zaimplementować proste menu za pomocą selectpolecenia. Skrypt (do celów testowych) wygląda następująco:

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

Skrypt nie rozpoznaje podanych przeze mnie prawidłowych danych wejściowych i zawsze drukuje komunikat „nieprawidłowa opcja”. Co robię źle w tym skrypcie?

Sumod
źródło
4
Twój wkład to 1, 2 lub 3, prawda?
enzotib

Odpowiedzi:

11

Twoje menu pokazane przez select będzie wyglądać następująco:

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

W tym momencie wpisujesz „1”, „2” lub „3”: nie wpisujesz słowa.

Ponadto selectbędzie się zapętlać, dopóki nie zobaczy breakpolecenia, więc chcesz to:

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

Jeśli chcesz zezwolić użytkownikowi na wpisanie numeru lub słowa, możesz napisać to:

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

Przecinek nie ma znaczenia składniowego, po prostu jest w stanie dopasować wzorzec albo do zmiennej $ REPLY (która faktycznie wpisał użytkownik), albo do zmiennej $ opt

Glenn Jackman
źródło
selectKomenda potrzebuje break, nie case.
glenn jackman
Dzięki! Nie zdawałem sobie sprawy, że były to opcje numeryczne. Hه!
Sumod
Hah, ja też programuję w C i potrzebujesz go breakw każdej sekcji. Jednak nigdy nie będziesz potrzebować breakw przypadku ... esac bloku w skrypcie powłoki . Może się to zdarzyć tak łatwo, aby je pomieszać. :-)
składniaerror
1
@syntaxerror, masz rację, nie trzeba breakza case. Musisz jednak breakuciec z selectpętli.
glenn jackman
@glenn jackman Chciałbym, aby to zmieniło się w bardziej pomocny komentarz (patrz dalej). Byłoby wspaniale, gdybyś zgodził się na usunięcie swojego komentarza od godziny 12:55. Oczywiście zrobię to samo z moim.
składniaerror
3

Twoja $optzmienna będzie ustawiona na słowie opcji odpowiadającej liczbie tej wejść użytkowników. Jeśli chcesz zobaczyć, co użytkownik wpisał, spójrz na $REPLY.

Kusalananda
źródło
1
Biorąc pod uwagę, że caseporównuje się $optz „apache”, „nazwany” i „sendmail”, jest to poprawne i nic nie trzeba zmieniać.
manatwork
@manatwork, chyba że OP chce, aby użytkownik wpisał słowa „apache”, „nazwany” lub „sendmail” zamiast naciskać 1, 2 lub 3.
Kusalananda
Ciekawy. $ REPLY posiada 1/ 2/ 3, a $ opt posiada apache/ named/sendmail
Peter.O
@ fred, tak, $REPLYjest tym, co wpisał użytkownik, a jeśli był to prawidłowy numer, to $optbędzie to słowo odpowiadające temu numerowi.
Kusalananda