What you're doing is tricky. The normal way is to avoid this and just pass the array values as arguments. In order to have both options, you would have to use eval
:
#!/bin/bash
function populate_array () {
if [ "$#" -gt 0 ] ; then
# Enter array w/ elements as argument of executable
# Note the quotes, they are needed
array=("$@");
n=$#
else
# Invoke executable with no arg, enter array element later
# Read a string instead of an array and use eval to make it
# into an array. That way, you can use tricks like escaping
# spaces. You also need the -r option to protect the backslashes
# so that eval will see them.
read -r -p "Enter array elements separated by spaces: " string
eval array="( $(printf '%s\n' "$string") )"
n=${#array[@]}
fi
printf "%d array elements \n" "$n"
}
populate_array "$@"
while (("$n" > 0)) # while [ "$n" -gt 0 ] ALSO WORKS
do
printf "%s \n" "${array[$n-1]}"
n=$n-1
done
exit 0
You still need to escape the parentheses if you pass the array values as an argument since ( )
are reserved characters for bash. With that caveat, the script above should work as you expect:
$ foo.sh lkl1239 343.4l 3,344 \(34\) "lklk lkl" lkaa\ lkc
6 array elements
lkaa lkc
lklk lkl
(34)
3,344
343.4l
lkl1239
And
$ foo.sh
Enter array elements separated by spaces: lkl1239 343.4l 3,344 \(34\) "lklk lkl" lkaa\ lkc
6 array elements
lkaa lkc
lklk lkl
(34)
3,344
343.4l
lkl1239
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.
Best Answer
The problem it is, that you probably made a
Ctrl+C
Ctrl+V
from a website, and the end-of-line char there was something strange, not printable character. (You can make it visible by dumping to hex the file.)Please open your file in an editor, and retype everything manually, or at least remove the last eol characters, save your work, and try again.