I think the easiest way would be to wrap the prompting code into a function, and then drop it into an until loop.
Since all you need really is to call the function until it succeeds, you can put the noop command ":" in the until loop.
Something like this:
#!/bin/bash
getgender() {
read -p "What is the gender of the user? (male/female): " gender
case "$gender" in
m|M)
grouptoaddto="boys"
return 0
;;
f|F)
grouptoaddto="girls"
return 0
;;
*)
printf %s\\n "Please enter 'M' or 'F'"
return 1
;;
esac
}
until getgender; do : ; done
sudo usermod -a -G "$grouptoaddto" "$username"
The point here is the function called with until, so it is repeatedly called until it succeeds. The case switch within the function is just an example.
Simpler example, without using a function:
while [ -z "$groupname" ]; do
read -p "What gender is the user?" answer
case "$answer" in
[MmBb]|[Mm]ale|[Bb]oy) groupname="boys" ;;
[FfGg]|[Ff]emale|[Gg]irl) groupname="girls" ;;
*) echo "Please choose male/female (or boy/girl)" ;;
esac
done
sudo usermod -a -G "$groupname" "$username"
In this last example, I'm using the -z switch to the [ (test) command, to continue the loop as long as the "groupname" variable has zero length.
The keynote is the use of while or until.
To translate this last example into human readable pseudocode:
While groupname is empty,
ask user for gender.
If he answers with one letter "m" or "B",
or the word "Male" or "boy",
set the groupname as "boys".
If she answers with one letter "F" or "g",
or the word "female" or "Girl",
set the groupname as "girls".
If he/she answers anything else, complain.
(And then repeat, since groupname is still empty.)
Once you have groupname populated,
add the user to that group.
Yet another example, without the groupname variable:
while true; do
read -p "What gender is the user?" answer
case "$answer" in
[MmBb]|[Mm]ale|[Bb]oy)
sudo usermod -a -G boys "$username"
break
;;
[FfGg]|[Ff]emale|[Gg]irl)
sudo usermod -a -G girls "$username"
break
;;
*) echo "Please choose male/female (or boy/girl)" ;;
esac
done