如何在bash中提示是否输入yes或no?

26

如何在Bash中询问是/否类型的问题?

我提出问题...echo "你喜欢馅饼吗?"

并接收回答...read pie

如果答案是 yes 或以 y 开头(所以类似 yes 和 yeah 的答案也可以),我该怎么做?


2
对于zsh用户,可用-q选项从终端只读取一个字符,并将名称设置为“y”,如果该字符是“y”或“Y”,否则设置为“n”。使用此标志设置返回状态仅在字符为“y”或“Y”时为零。请注意,即使与-p、-u或-z标志或重定向输入一起使用,它也始终从终端读取。此选项也可以在zle小部件中使用。 - Ulysse BN
1
@UlysseBN zsh 令我惊叹不已!我不记得这个原始问题是什么了,但我将牢记在心,当我控制执行我的脚本的shell时会用到 - 谢谢! - Ben Aubin
6个回答

35

我喜欢使用以下函数:

function yes_or_no {
    while true; do
        read -p "$* [y/n]: " yn
        case $yn in
            [Yy]*) return 0  ;;  
            [Nn]*) echo "Aborted" ; return  1 ;;
        esac
    done
}

因此,在您的脚本中,您可以像这样使用:

yes_or_no "$message" && do_something

如果用户按下除 [yYnN] 以外的任何键,它将重复显示该消息。


1
“read -p” "$@ [y/n]: "是不正确的,你需要使用$*,否则如果函数被调用时带有多个参数,读取将会出错。此外,从技术上讲,这应该使用yes_or_not "$@",但仅当您使用yes_or_not 'foo bar'并且用户没有输入yes或no时才会发生(内部空格将会丢失)。 - Etan Reisner
这真是太棒了 :) - Ben Aubin
我在 $* 后面添加了一个问号...这也可以很好地与 if 块一起使用: if yes_or_no "Do next task"; then ;;;; fi 结构。 - phyatt
我会将yn定义为局部变量,以避免污染全局作用域。 - onlycparra

16

这也可以运行:

read -e -p "Do you like pie? " choice
[[ "$choice" == [Yy]* ]] && echo "doing something" || echo "that was a no"

以 Y 或 y 开头的模式将被视为 yes


出于好奇,包含“-e”和“-p”标志的原因是什么? - twhitney
@twhitney请查看read --help以获取详细信息。 - Jahid
读取:错误选项:-h。不错。 - Nebulosar
你可以在这个博客中找到更多信息:https://www.linuxscrew.com/bash-prompt-for-input - Nebulosar

12

我喜欢Jahid的一行代码。这是它的一个稍微简化的版本:

[[ "$(read -e -p 'Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]]

这里是一些测试:

$ [[ "$(read -e -p 'Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]] && echo Continuing || echo Stopping

Continue? [y/N]> yes
Continuing

$ for test_string in y Y yes YES no ''; do echo "Test String: '$test_string'"; echo $test_string | [[ "$(read -e -p 'Continue? [y/N]>'; echo $REPLY)" == [Yy]* ]] && echo Continuing || echo Stopping; done

Test String: 'y'
Continuing

Test String: 'Y'
Continuing

Test String: 'yes'
Continuing

Test String: 'YES'
Continuing

Test String: 'no'
Stopping

Test String: ''
Stopping

更新

针对一条评论,我将添加一项改编以使其在zsh中可行。

免责声明

尽管现在我主要使用zsh作为交互式shell,但我永远不会在zsh中编写脚本。我仍然使用bashsh编写所有的脚本。 然而,由于有时您需要对交互式shell进行脚本修改(例如:source ~/dev/set_env),因此您可能希望包含提示。

#! /usr/bin/env zsh
[[ "$(echo -n 'Continue? [y/N]> ' >&2; read; echo $REPLY)" == [Yy]* ]] \
  && echo Continuing \
  || echo Stopping

这仅适用于 bash 读取,不适用于 zsh 读取。 - Akhil
3
我为你添加了一个 zsh 的例子。☮️❤️ - Bruno Bronosky
zsh 中使用 ? 附加符号对我有效。例如 [[ "$(read -e '?是否继续?[y/N]> '; echo $REPLY)" == [Yy]* ]]。参考资料:https://superuser.com/questions/555874/zsh-read-command-fails-within-bash-function-read1-p-no-coprocess - Akhil

6

这个有效:

echo "Do you like pie?"
read pie
if [[ $pie == y* ]]; then
    echo "You do! Awesome."
else
    echo "I don't like it much, either."
fi

[[ $pie == y* ]] 用于测试变量 $pie 是否以 y 开头。

如有需要,可自由修改。


4
与其他答案不同,这个函数为您提供了设置默认值的可能性:
function askYesNo {
        QUESTION=$1
        DEFAULT=$2
        if [ "$DEFAULT" = true ]; then
                OPTIONS="[Y/n]"
                DEFAULT="y"
            else
                OPTIONS="[y/N]"
                DEFAULT="n"
        fi
        read -p "$QUESTION $OPTIONS " -n 1 -s -r INPUT
        INPUT=${INPUT:-${DEFAULT}}
        echo ${INPUT}
        if [[ "$INPUT" =~ ^[yY]$ ]]; then
            ANSWER=true
        else
            ANSWER=false
        fi
}

askYesNo "Do it?" true
DOIT=$ANSWER

if [ "$DOIT" = true ]; then
    < do some stuff >
fi

在命令行中,您将看到:
Do it? [Y/n] y

0
这是一个简短的函数:
prompt(){ read -p "$1" a; [ $a = "y" ]; }

使用方法(如果答案是y,则执行do_something):

prompt "Do you want it?"  &&  do_something

使用多个命令的方法:

prompt "Do you want it?" && {
  do_something1
  do_something2
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接