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

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.