1

I am quite new to Unix and I need help with this case statement. What I want to do is to make the user select a variable with a case statement and then make the system read the result of the choice made by the user. Here is my script structure (as an example):

CHOOSEfruit () {
clear
echo "Choose fruit you need to buy (a.Apple b.Banana c.Pear d.Pineapple)"
read FRUIT
case $FRUIT in
    a|A)
    echo "Apple"
    ;;
    b|B)
    echo "Banana"
    ;;
    c|C)
    echo "Pear"
    ;;
    d|D)
    echo "Pineapple"
    ;;
esac
clear
echo "The fruit you need to buy is $FRUIT"
echo ""
read -p "Press [Enter] key to go back to main menu"
clear
}

If I choose "a", I want my script to output: "The fruit you need to buy is Apple"

2 Answers 2

5

This would be better solved by a select loop:

PS3='Please select fruit from the menu: '

select fruit in 'No fruit please' Apple Banana Pear Pineapple; do
    case $REPLY in
        1)
            # User wants no fruit
            unset fruit
            break
            ;;
        [2-5])
            # All ok, exit loop
            break
            ;;
        *)
            # Invalid choice
            echo 'Try again' >&2
    esac
done

if [ -n "$fruit" ]; then
    printf 'The fruit you need is %s\n' "$fruit"
else
    echo 'You selected no fruit!'
fi

The select loop presents a list of choices to a user in an interactive menu. The prompt given to the user for selecting an item from the menu is the string in $PS3.

In the body of the select loop, the value in $fruit will be the actual text string that the user selected, while $REPLY will be whatever the user typed at the prompt.

Note that there is no need to use a case ... esac statement in the loop. You could use any code here. For example, you may feel more comfortable using if ... then ... elif ... else ... fi:

if [ "$REPLY" = 1 ]; then
    unset fruit
    break
elif [[ $REPLY == [2-5] ]]; then
    break
else
    echo 'Try again' >&2
fi

The select loop is exited with break, just like any other infinite loop.

Three runs of this code:

$ bash script
1) No fruit please
2) Apple
3) Banana
4) Pear
5) Pineapple
Please select fruit from the menu: 1
You selected no fruit!
$ bash script
1) No fruit please
2) Apple
3) Banana
4) Pear
5) Pineapple
Please select fruit from the menu: 2
The fruit you need is Apple
$ bash script
1) No fruit please
2) Apple
3) Banana
4) Pear
5) Pineapple
Please select fruit from the menu: 6
Try again
Please select fruit from the menu: 3
The fruit you need is Banana
4

You almost got it right. Simply edit your case statement like this:

case $FRUIT in
    a|A)
    FRUIT="Apple"
    ;;
    b|B)
    FRUIT="Banana"
    ;;
    c|C)
    FRUIT="Pear"
    ;;
    d|D)
    FRUIT="Pineapple"
    ;;
esac
2
  • 1
    This looks awkward (longwinded). Better with FRUIT=${fruitmap[${REPLY^^}]} where $REPLY is what the user is entering and fruitmap is an associative array of letter-to-fruit mappings. declare -A fruitmap=( [A]=Apple [B]=Banana ... )
    – Kusalananda
    Feb 16, 2021 at 18:19
  • 1
    I know there is room for improvement. I just wanted to let OP know what he missed in his solution. :)
    – BlueManCZ
    Feb 16, 2021 at 22:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .