如何在bash脚本中提示用户确认?

How do I prompt a user for confirmation in bash script?

本问题已经有最佳答案,请猛点这里访问。

我想快速地写一句"你确定吗?"提示在潜在危险的bash脚本顶部进行确认,最简单/最好的方法是什么?


1
2
3
4
5
6
read -p"Are you sure?" -n 1 -r
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
    # do dangerous stuff
fi

我采纳了Levisle85的建议(谢谢!)在read中添加了-n选项来接受一个字符,而无需按enter。您可以使用其中一个或两个。

另外,否定的形式可能如下所示:

1
2
3
4
5
6
read -p"Are you sure?" -n 1 -r
echo    # (optional) move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
    [["$0" ="$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell
fi

但是,正如Erich所指出的,在某些情况下,例如脚本在错误的shell中运行所导致的语法错误,被否定的形式可能会使脚本继续运行到"危险的东西"。故障模式应倾向于最安全的结果,因此只应使用第一个非否定的if

说明:

read命令输出提示(-p"prompt"然后接受一个字符(-n 1并接受反斜杠字面(-r)(否则read会将反斜杠视为转义,等待第二个字符)。如果不提供这样的名称,那么用于存储结果的read的默认变量是$REPLYread -p"my prompt" -n 1 -r my_var

if语句使用正则表达式检查$REPLY中的字符是否与(=~中的字符)的大小写"y"匹配。这里使用的正则表达式表示"一个字符串,从(^开始,仅由括号表达式([Yy]和结束($中的一个字符列表组成)"。锚(^$防止匹配较长的字符串。在这种情况下,它们有助于加强read命令中设置的一个字符限制。

否定形式使用逻辑"not"运算符(!)来匹配(=~)任何非"y"或"y"的字符。另一种表达这一点的方法可读性较低,在我看来,在这种情况下也不能如此清晰地表达意图。然而,这就是它的样子:if [[ $REPLY =~ ^[^Yy]$ ]]


使用案例/ESAC。

1
2
3
4
5
6
read -p"Continue (y/n)?" choice
case"$choice" in
  y|Y ) echo"yes";;
  n|N ) echo"no";;
  * ) echo"invalid";;
esac

优势:

  • 尼特
  • 可以更容易地使用"或"条件
  • 可以使用字符范围,例如[YY][EE][SS]接受单词"是",其中任何字符可以是小写或大写。

  • 这样就可以得到"Y"、"Yes"或"Enter"

    1
    2
    3
    4
    5
     read -r -p"Are you sure? [Y/n]" response
     response=${response,,} # tolower
     if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
        your-action-here
     fi

    如果使用zsh,请尝试以下操作:

    1
    2
    3
    4
    5
    read"response?Are you sure ? [Y/n]"
    response=${response:l} #tolower
    if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
        your-action-here
    fi


    试试read外壳内置:

    1
    2
    3
    4
    5
    6
    read -p"Continue (y/n)?" CONT
    if ["$CONT" ="y" ]; then
      echo"yaaa";
    else
      echo"booo";
    fi

    我使用的功能如下:

    1
    2
    3
    4
    5
    6
    7
    function ask_yes_or_no() {
        read -p"$1 ([y]es or [N]o):"
        case $(echo $REPLY | tr '[A-Z]' '[a-z]') in
            y|yes) echo"yes" ;;
            *)     echo"no" ;;
        esac
    }

    以及一个使用它的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    if [["no" == $(ask_yes_or_no"Are you sure?") || \
         "no" == $(ask_yes_or_no"Are you *really* sure?") ]]
    then
        echo"Skipped."
        exit 0
    fi

    # Do something really dangerous...
    • 输出总是"是"或"否"
    • 默认为"否"
    • 除了"y"或"yes"以外的所有东西都返回"no",所以对于危险的bash脚本来说是相当安全的。
    • 它是不区分大小写的,"y"、"yes"或"yes"都是"yes"。

    希望您喜欢,
    干杯!


    这就是我在别处发现的,有更好的版本吗?

    1
    2
    3
    4
    read -p"Are you sure you wish to continue?"
    if ["$REPLY" !="yes" ]; then
       exit
    fi


    1
    2
    3
    [[ -f ./${sname} ]] && read -p"File exists. Are you sure?" -n 1

    [[ ! $REPLY =~ ^[Yy]$ ]] && exit 1

    在函数中使用此函数查找现有文件并在覆盖前提示。


    1
    2
    3
    4
    5
    6
    7
    #!/bin/bash
    echo Please, enter your name
    read NAME
    echo"Hi $NAME!"
    if ["x$NAME" ="xyes" ] ; then
     # do something
    fi

    我是一个在bash中阅读并回送结果的简短脚本。


    1
    2
    3
    4
    5
    6
    echo are you sure?
    read x
    if ["$x" ="yes" ]
    then
      # do the dangerous stuff
    fi

    QND:使用

    1
    2
    read VARNAME
    echo $VARNAME

    对于没有readline支持的单行响应。然后根据需要测试$varname。