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