Array based selection of values by selecting either index or member

say I have

istofitems="beans  rice  carrots  radishes rutabaga spinach"

and I want the end user to select something like below

Please enter the veg you like from 

 1 ) beans 
 2) rice 
 3) carrots 
4) radishes 
5) rutabaga 
6) spinach
Q) Quit

Enter either Value or Number:  <- user enters either number corresponding to entry or the name 

and return the user selection in a variable.

now the problem is that the list is always variables -- today it has 6 members, later on it may grow to 20, and I can't add them to the list manually... All I can is add them to list in first place.

How about this using the shell select internal

listofitems="beans rice carrots radishes rutabaga spinach"
MU=( $listofitems Quit )

while true
do
    echo "Please enter the veg you like from"
    select opt in "${MU[@]}"
    do

        if [ "$opt" != "" ]
        then
            echo "You selected $opt"
            break 3
        fi
        # Check REPLY against the array:
        for opt in ${MU[@]}
        do
           if [ $REPLY = "$opt" ]
           then
               echo "You selected $opt"
               break 3
           fi
        done
        echo "Illegal selection"
        break
    done
done

It turned out to be a good toy :slight_smile:

#!/bin/bash
choose() {
  select button in $@ Quit; do
    case $button in
      Quit)
        echo $REPLY - $button
        break;;
      *)  
        echo you press $REPLY and chose $button
    esac
done
}

choose  $listofitems

Need to refine error handling

choose() {
  select button in $@ Quit; do
    case $button in
      Quit)
        echo $REPLY - $button
        break
        ;;
      "") 
        echo ERROR try again
        continue
        ;;
      *)  
        echo you press $REPLY and selected $button
    esac
done
}

choose $listofitems
1 Like

Nice procedure nezabudka, but original request was selection of item by number or by name:

For a higher level of difficulty how about spaces in the options:

#!/bin/bash
listofitems="fried rice,boiled rice,beans,carrots,radishes,rutabaga,spinach"
IFS=, MU=( $listofitems quit )

while true
do
    echo "Please enter the veg you like from"
    select opt in "${MU[@]}"
    do
        [ "$opt" != "" ] && break 3
        # Check REPLY against the array:
        for opt in ${MU[@]}
        do
           [ "$REPLY" = "$opt" ] && break 3
        done
        echo "Illegal selection - try again"
        break
    done
done
echo "You typed $REPLY and selected $opt"
$ ./menu
Please enter the veg you like from
1) fried rice   3) beans        5) radishes     7) spinach
2) boiled rice  4) carrots      6) rutabaga     8) quit
#? none
Illegal selection - try again
Please enter the veg you like from
1) fried rice   3) beans        5) radishes     7) spinach
2) boiled rice  4) carrots      6) rutabaga     8) quit
#? boiled rice
You typed boiled rice and selected boiled rice

$ ./menu
Please enter the veg you like from
1) fried rice   3) beans        5) radishes     7) spinach
2) boiled rice  4) carrots      6) rutabaga     8) quit
#? 7
You typed 7 and selected spinach

If you have bash 4.0 or higher use below for case insensitive matching (eg type QUIT instead of quit )
[ "${REPLY,,}" = "${opt,,}" ] && break 3

2 Likes