如何让 bash 文件根据用户输入以不同的方式回显?

如何让 bash 文件根据用户输入以不同的方式回显?

我对 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应该只是yesno,因为您只想要字符串yesno

您可以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

总结:修复语法错误,确保测试中确实有非空变量[,并创建一个函数将其传输到管道teefestival

至于打印到屏幕并输出到festival,我个人会将脚本包装成一个函数并将所有内容通过管道传输到festivaltee中间是(将文本同时发送到屏幕和管道)。

然而,有三个语法问题需要修复:

  • read $input应该是read input$符号取消引用 shell 脚本中的变量(即,它将$input被替换为input保留的内容)。
  • 您没有声明yesno变量。您应该做的是字符串比较:[ "$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

相关内容