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

Tom*_*Tom 561 bash

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

Pau*_*ce. 893

read -p "Are you sure? " -n 1 -r
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
    # do dangerous stuff
fi
Run Code Online (Sandbox Code Playgroud)

我结合levislevis85的建议(感谢!),并添加-n选项,以read接受,而不需要按一个字符Enter.您可以使用其中一个或两个.

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

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
Run Code Online (Sandbox Code Playgroud)

然而,正如Erich所指出的,在某些情况下,例如由于脚本在错误的shell中运行而导致的语法错误,否定的形式可能允许脚本继续"危险的东西".失败模式应该有利于最安全的结果,因此只if应使用第一个,不被否定的.

说明:

read命令输出prompt(-p "prompt")然后接受一个字符(-n 1)并逐字接受反斜杠(-r)(否则read会将反斜杠视为转义并等待第二个字符).read存储结果的默认变量是,$REPLY如果您不提供如下名称:read -p "my prompt" -n 1 -r my_var

if语句使用正则表达式来检查$REPLYmatches(=~)中的字符是大写还是小写"Y".这里使用的正则表达式是"一个字符串starting(^),它只包含一个括号表达式([Yy])和结束($)" 中的一个字符列表.锚(^$)防止匹配更长的字符串.在这种情况下,它们有助于强化命令中的单字符限制集read.

否定形式使用逻辑"not"运算符(!)匹配(=~)任何不是"Y"或"y"的字符.表达这种情况的另一种方式是可读性较差,并且在这种情况下我并未明确表达我的意图.但是,这就是它的样子:if [[ $REPLY =~ ^[^Yy]$ ]]

  • 在"读取"之后,你应该做一个"回声",让光标回到下一行.(只是没有参数的原始"回声"就可以了) (20认同)
  • @tuner:如果没有提供变量名,则自动设置`$ REPLY`. (11认同)
  • 只是对否定形式的警告 - 如果你的用户在旧的Bourne`sh` shell中运行,那么读取和有条件[[将失败但脚本将继续而不退出 - 可能不希望你想要 - 正面的风险]因此版本更安全 (6认同)
  • 只是要指出 - 在测试时会忘记顶部的hashbang的新手错误会引发错误.确保将#!/ usr/bin/env bash(或类似的有效hashbang)添加到脚本的顶部 (5认同)
  • 这样的结构怎么样:`[[$ REPLY =〜^ [Yy] $]] || 退出-1`旧的shell如何评估它? (3认同)
  • 它具有比`[]`更多的功能,包括正则表达式匹配运算符`= ~`.请参阅:http://mywiki.wooledge.org/BashFAQ/031 (2认同)

gho*_*g74 161

用例/ esac.

read -p "Continue (y/n)?" choice
case "$choice" in 
  y|Y ) echo "yes";;
  n|N ) echo "no";;
  * ) echo "invalid";;
esac
Run Code Online (Sandbox Code Playgroud)

优点:

  1. 整洁
  2. 可以更容易地使用"OR"条件
  3. 可以使用字符范围,例如[yY] [eE] [sS]接受单词"yes",其中任何字符可以是小写字母或大写字母.

  • 好的解决方案 就个人而言,如果bash脚本真的可能瘫痪我喜欢让这个人输入'是'. (7认同)
  • 当用户输入无效时,如何要求用户再次输入.做'回归' 如果三次无效 (3认同)
  • @SiegeX如果确实如此,真的瘫痪你可以让用户输入"快速的棕色狐狸跳过懒狗":P (2认同)

Ada*_*upp 33

试试readshell内置:

read -p "Continue (y/n)?" CONT
if [ "$CONT" = "y" ]; then
  echo "yaaa";
else
  echo "booo";
fi
Run Code Online (Sandbox Code Playgroud)


Ser*_*ujo 31

通过这种方式,您可以得到"是"或"输入"

 read -r -p "Are you sure? [Y/n]" response
 response=${response,,} # tolower
 if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
    your-action-here
 fi
Run Code Online (Sandbox Code Playgroud)

如果你使用zsh试试这个:

read "response?Are you sure ? [Y/n] "
response=${response:l} #tolower
if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
    your-action-here
fi
Run Code Online (Sandbox Code Playgroud)

  • 在正则表达式中,没有必要匹配yes和y,只需y开头即可.此外,如果默认值必须为no,那么以下内容将会有所帮助.读"响应?你确定吗?[Y/n]"&& if [["$ response"=〜^ [Yy]]]; 然后回应"是的,你做到了."; 否则回应"不,狭隘逃脱"; 科幻 (2认同)

Séb*_*rra 20

这是我使用的功能:

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
}
Run Code Online (Sandbox Code Playgroud)

并使用它的一个例子:

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...
Run Code Online (Sandbox Code Playgroud)
  • 输出始终为"是"或"否"
  • 默认情况下它是"否"
  • 除"y"或"yes"之外的所有内容都返回"no",因此对于危险的bash脚本来说非常安全
  • 它不区分大小写,"Y","是"或"是"的工作为"是".

我希望你喜欢,
干杯!


Tom*_*Tom 17

这是我在别处找到的,是否有更好的版本?

read -p "Are you sure you wish to continue?"
if [ "$REPLY" != "yes" ]; then
   exit
fi
Run Code Online (Sandbox Code Playgroud)


Bra*_*ley 6

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

[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
Run Code Online (Sandbox Code Playgroud)

在函数中使用它来查找现有文件并在覆盖之前提示.

  • Parser抱怨`return`在函数外面,你可能意味着`退出`.我仍然喜欢你的答案,因为如果确认,它不会缩进要执行的代码. (2认同)

小智 5

echo are you sure?
read x
if [ "$x" = "yes" ]
then
  # do the dangerous stuff
fi
Run Code Online (Sandbox Code Playgroud)