7

I am trying to implement a simple menu using the select command. The script (for testing purposes) is as follows:

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

The script is not recognizing any valid inputs I give and always prints the "invalid option" message. What am doing wrong in this script?

  • 3
    Your input is 1, 2 or 3, right? – enzotib Sep 14 '11 at 12:46
9

Your menu shown by select will look like:

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

At this time, you enter "1" or "2" or "3": you don't type the word.

Also, select will loop until it sees a break command, so you want this:

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

If you wanted to allow the user to enter either the number or the word, you could write this:

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

The comma has no syntactical significance, it's just there to be able to pattern match on either the $REPLY variable (which is what the user actually typed) or the $opt variable

  • The select command needs a break, not case. – glenn jackman Sep 14 '11 at 18:09
  • Thanks! I did not realize that it was numerical options. Duhh! – Sumod Sep 15 '11 at 10:45
  • Hah, I too program in C and, you do need a break there in every section. However, you will never need a break in a case...esac block in a shell script. It can happen so easily to get them mixed up. :-) – syntaxerror Nov 20 '14 at 11:05
  • 1
    @syntaxerror, you're right, you don't need break for case. However, you need a break to escape the select loop. – glenn jackman Nov 20 '14 at 12:55
  • @glenn jackman I would like to have this turned into a more helpful comment (see next). So it would be great if you agreed on deleting your comment from 12:55. I will do the same with mine, of course. – syntaxerror Nov 23 '14 at 16:20
3

Your $opt variable will be set to the option word corresponding to the number that the user inputs. If you want to look at what the user actually typed, look at $REPLY.

  • 1
    Given that the case compares $opt against "apache", "named" and "sendmail", it is correct and nothing has to be changed. – manatwork Sep 14 '11 at 14:13
  • @manatwork, unless the OP wants the user to type in the words "apache", "named" or "sendmail" rather than pressing 1, 2 or 3. – Kusalananda Sep 14 '11 at 14:38
  • Interesting. $REPLY holds 1/2/3, and $opt holds apache/named/sendmail – Peter.O Sep 15 '11 at 6:50
  • @fred, yes, $REPLY is whatever the user typed, and if it was a valid number then $opt will be the word corresponding to that number. – Kusalananda Sep 15 '11 at 6:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.