我对 shell 脚本还不太熟悉,但我想编写一个基本脚本,让 bash 文件根据用户输入回显不同的文本行。例如,如果脚本询问用户“你在吗?”并且用户输入的是“是”或“是”,那么脚本将回显“你好!”之类的内容。但如果用户输入的是“否”或“否”,脚本将回显其他内容。最后,如果用户输入的不是“是/是”或“否/否”,脚本将回显“请回答是或否”。以下是我目前所拥有的:
echo "Are you there?"
read $input
if [ $input == $yes ]; then
echo "Hello!"
elif [ $input == $no ]]; then
echo "Are you sure?"
else
echo "Please answer yes or no."
fi
但是,无论输入什么,我总是得到第一个响应(“你好!”)
另外,我想将文本转语音功能纳入其中(就像我使用 festival 处理其他 bash 文件项目一样)。在其他 bash 文件中,我是这样操作的:
echo "Hello!"
echo "Hello!" | festival --tts
有没有办法将其合并到上面的 if then/yes no 提示中?提前谢谢您,我正在使用它来制作简单的 bash 文件并帮助自己学习。
答案1
主要问题在这里:
read $input
在 bash 中,通常$foo
是变量的值foo
。在这里,你不需要值,而是变量的名称,因此应该只是:
read input
类似地,在if
测试中,$yes
和$no
应该只是yes
和no
,因为您只想要字符串yes
和no
。
您可以case
在此处使用一个语句,它(恕我直言)可以更轻松地根据输入执行多种情况:
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
您可以包装这两个echo
语句并将其使用festival
在一个函数中以避免重复:
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
使用$input
,bash 将其替换为其值,该值最初为零,因此read
运行的命令是:
read
默认情况下,read
将输入存储在变量中REPLY
。因此,如果您愿意,可以input
完全消除变量,而使用$REPLY
代替$input
。
另请参阅该select
声明在 Bash 中。
答案2
总结:修复语法错误,确保测试中确实有非空变量[
,并创建一个函数将其传输到管道tee
中festival
。
至于打印到屏幕并输出到festival
,我个人会将脚本包装成一个函数并将所有内容通过管道传输到festival
,tee
中间是(将文本同时发送到屏幕和管道)。
然而,有三个语法问题需要修复:
read $input
应该是read input
。$
符号取消引用 shell 脚本中的变量(即,它将$input
被替换为input
保留的内容)。- 您没有声明
yes
和no
变量。您应该做的是字符串比较:[ "$input" == "yes" ]
- 额外
]]
elif
至于为什么你Hello!
总是得到,那正是因为前两个要点。在read $input
变量input
不存在之前,所以你只是在执行read
(即,不存在的变量$input
被取消引用为空字符串,只留下read
命令)。因此,无论你输入什么,都会存储在变量中REPLY
,这是read
在没有给出变量名时使用的。而且因为yes
变量不存在,它也会被替换为空字符串。因此在现实中[ $input == $yes ]
被视为[ "" == "" ]
始终为真。
$ [ $nonexistent == $anothernonexistent ] && echo "Success"
Success
修复后的脚本如下:
#!/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
记得引用变量并阅读测试命令中的=
和之间的区别==
。
答案3
第三种方法是将每个案例分配给一个公共变量,最后对该变量采取行动。我不确定这种方法在 bash 中有多常见,但在其他编程语言中,这是相当标准的。
还可shopt -s nocasematch
与 结合使用,进行[[
不区分大小写的字符串比较。
同时,YES
和 也NO
被视为有效输入。
#!/bin/bash
shopt -s nocasematch
read -p "Are you there?" input
if [[ "$input" == "yes" ]]; then
msg="Hello!"
elif [[ "$input" == "no" ]]; then
msg="Are you sure?"
else
msg="Please answer yes or no."
fi
echo $msg
echo $msg | festival --tts