Craig van Tonder
Craig van Tonder

Reputation: 7687

Bash - Iterating over select menu options after choosing an option?

I am reading up on Select menus in Bash:

Making menus with the select built-in

I am quite confused when it comes to iterating over the options in the menu and would appreciate any feedback on this.

Using the code here as a starting point:

How can I create a select menu in a shell script?

We get the following output:

root@dev:~/# ./test.sh
1) Option 1
2) Option 2
3) Option 3
4) Quit
Please enter your choice: 1
you chose choice 1
Please enter your choice: 2
you chose choice 2
Please enter your choice: 4
root@dev:~/#

What I would like to try to do, is show the select options again once an option has been chosen, so the output would be like:

root@dev:~/# ./example.sh
1) Option 1
2) Option 2
3) Quit
Please enter your choice: 1
you chose choice 1
1) Option 1
2) Option 2
3) Quit
Please enter your choice: 2
you chose choice 2
1) Option 1
2) Option 2
3) Quit
Please enter your choice: 3
root@dev:~/#

So I have given this a Bash (L) and and tried to loop through the options (array?):

#!/bin/bash

PS3='Please enter your choice: '
options=("Option 1" "Quit")
select opt in "${options[@]}"
do
  case $opt in
    "Option 1")
      echo "you chose choice 1"
      # Create an incrementing value
      loop=1;
      # Loop through each option
      for option in ${options[@]} ; do
        # Echo the option
        echo "$loop) $option";
        # Increment the loop
        loop=$((loop+1));
      done
      ;;
    "Quit")
      break
      ;;
    *) echo invalid option;;
  esac
done

But then I get an output like:

root@dev:~/# ./stumped.sh
1) Option 1
2) Quit
Please enter your choice: 1
you chose choice 1
1) Option
2) 1
3) Quit
Please enter your choice:

So it seems that the array values are separated by spaces here?

To my understanding: options=("Option 1" "Quit") is creating an array of 2 values and not of 3 however it is being interpreted in Bash as 3 and I am not sure why.

Could someone enlighten me and explain why this is happening?

Upvotes: 1

Views: 2911

Answers (2)

Walter A
Walter A

Reputation: 20022

When you want the numbered options shown each iteration, let select do that for you.

options=("Option one" "two"  three "and number four"  quit)
while true; do
   select item in "${options[@]}" ; do
      if [ -n "${item}" ]; then
         break
      fi
      echo "Sorry, please enter a number as shown."
      break
   done;
   if [[ "${item}" = "quit" ]]; then
     break
   fi
   if [ -n "${item}" ]; then
      echo "Your answer is ${item}"
   fi
done

Upvotes: 0

salezica
salezica

Reputation: 76989

Let's create a function that shows the menu and echoes the user's choice:

function show_menu {
  select option in "${OPTIONS[@]}"; do
    echo $option
    break
  done
}

Now, we can wrap that function in a loop, and only break out if the user picked Quit:

while true; do
  option=$(show_menu)

  if [[ $option == "Quit" ]]; then
    break
  fi
done

Voila!

Upvotes: 2

Related Questions