Reputation: 25
I'm new to bash, and the below while loop is driving me crazy. I want the loop to exit when the user enters y or n but it fails to do so. I have tried different ways but no luck. Anyone can point me in the right direction?
echo "want to go for a walk Y/N "
read answer
while [ "$answer" != "y" ] || [ "$answer" != "n" ] ; do
echo "Enter y or n"
read answer
done
The second solution also is in the same scenario
echo "want to go for a walk Y/N "
read answer
while [ "$answer" != "y" || "$answer" != "n" ] ; do
echo "Enter y or n"
read answer
done
Upvotes: 0
Views: 1758
Reputation: 1035
Of course it won't exit. That loop never will.
In your code, answer
is always NOT 'y' OR NOT 'n' (together, at the same time).
It is so because if you select 'y' then it's NOT 'n' and if you select 'n' then it's NOT 'y'.
If you have TRUE || FALSE = TRUE
And if you have FALSE || TRUE = TRUE
, so the loop keeps going.
The condition you want to use is &&
(AND), so while answer
is NOT 'y' AND NOT 'n' then go on, but if it is one of them then exit.
TRUE && FALSE => FALSE
and FALSE && TRUE => FALSE
and that's what you need for the loop to finally end.
#!/bin/bash
echo "want to go for a walk y/n "
read -r answer
while [ "$answer" != "y" ] && [ "$answer" != "n" ] ; do
echo "Enter y or n"
read -r answer
done
The -r
flag in read -r var
is to avoid reading backslash as an escape character. It is not relevant for this toy problem but it is a best practice to include it.
Comment from David: Keep in mind that the code doesn't handle case, so Y is not recognized as y.
Upvotes: 2
Reputation: 19545
Don't forget in a while
loop, the first commands list may also contain multiple statements:
#!/usr/bin/env sh
echo "want to go for a walk y/n "
while
read -r answer
case $answer in
[yYnN]) false ;;
esac
do
echo "Enter y or n"
done
Or using until
and Bash's Extended Regular Expression:
#!/usr/bin/env bash
echo "want to go for a walk y/n "
until
read -r answer
[[ $answer =~ [yYnN] ]]
do
echo "Enter y or n"
done
And a featured, case-insensitive POSIX compatible implementation:
#!/usr/bin/env sh
echo "want to go for a walk y/n "
until
read -r answer
case $answer in
[yY])
echo "Handling Yes answer stuffs"
;;
[nN])
echo "Stuffs for No answer"
;;
*) # Landing here if invalid answer
false # Proceed with the do...done statements
;;
esac
do
echo "Enter y or n"
done
Upvotes: 0