How to ask a [Y/n] question in bash script? [duplicate]
The main problem is here:
read $input
In bash, usually, $foo
is the value of the variable foo
. Here, you don't want the value, but the name of the variable, so it should be just:
read input
Similarly, in the if
tests, $yes
and $no
should be just yes
and no
, since you just want the strings yes
and no
there.
You could use a case
statement here, which (IMHO) makes it easier to do multiple cases based on input:
case $input in
[Yy]es) # The first character can be Y or y, so both Yes and yes work
echo "Hello!"
echo "Hello!" | festival --tts
;;
[Nn]o) # no or No
echo "Are you sure?"
echo "Are you sure?" | festival --tts
;;
*) # Anything else
echo "Please answer yes or no."
echo "Please answer yes or no." | festival --tts
;;
esac
You could wrap the two echo
statements and the use of festival
in a function to avoid repeating yourself:
textAndSpeech ()
{
echo "$@"
echo "$@" | festival --tts
}
case $input in
[Yy]es) # The first character can be Y or y, so both Yes and yes work
textAndSpeech "Hello!"
;;
[Nn]o) # no or No
textAndSpeech "Are you sure?"
;;
*) # Anything else
textAndSpeech "Please answer yes or no."
;;
esac
With $input
, bash replaces this with its value, which is nothing initially, so the read
command run is:
read
And read
by default stores the input in the variable REPLY
. So you can, if you want, eliminate the input
variable altogether and use $REPLY
instead of $input
.
Also have a look at the select
statement in Bash.
TL;DR: fix syntax errors, ensure you actually have non-empty variables in [
test, and make a function to pipe through tee
into festival
.
As far as printing to screen and outputting to festival
, I personally would wrap the script into a function and pipe everything to festival
, with tee
in between (which sends text both to screen and pipe).
There's three syntax problems to fix, however:
-
read $input
should beread input
. The$
symbol dereferences variable in shell scripting (i.e., it$input
will be replaced with whatinput
holds). - You've no
yes
andno
variables declared. What you should be doing is string comparison:[ "$input" == "yes" ]
- Extra
]]
inelif
As for why you get Hello!
all the time, that's exactly because of first two bullet points. Before read $input
the variable input
doesn't exist, so you're only performing read
(i.e., nonexistent variable $input
is dereferenced into empty string, leaving only read
command there). So whatever you type gets stored in the REPLY
variable which is what read
uses when no variable name has been given. And because yes
variable doesn't exist, that gets replaced with empty string too. Thus in reality [ $input == $yes ]
is treated as [ "" == "" ]
which is always true.
$ [ $nonexistent == $anothernonexistent ] && echo "Success"
Success
The fixed script should be as so:
#!/bin/bash
main(){
read -p "Are you there?" input
if [ "$input" == "yes" ]; then
echo "Hello!"
elif [ "$input" == "no" ]; then
echo "Are you sure?"
else
echo "Please answer yes or no."
fi
}
main | tee /dev/tty | festival --tts
Remember to quote the variables and read up on difference between =
and ==
in test command.