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

Posted

技术标签:

【中文标题】如何在 bash 脚本中提示用户进行确认? [复制]【英文标题】:How do I prompt a user for confirmation in bash script? [duplicate] 【发布时间】:2010-12-25 12:36:25 【问题描述】:

我想简短地说“你确定吗?”在潜在危险的 bash 脚本顶部提示确认,最简单/最好的方法是什么?

【问题讨论】:

Related 【参考方案1】:
read -p "Are you sure? " -n 1 -r
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
    # do dangerous stuff
fi

我采纳了 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

然而,正如 Erich 所指出的,在某些情况下,例如由于脚本在错误的 shell 中运行而导致语法错误,否定形式可能会让脚本继续“危险的东西”。故障模式应该有利于最安全的结果,因此应该只使用第一个非否定的if

解释:

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

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

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

【讨论】:

在“read”之后你应该做一个“echo”来让光标回到下一行。 (只是一个没有参数的原始“回声”就可以了) @tuner: 如果没有提供变量名,$REPLY 会自动设置。 只是对否定形式的警告 - 如果您的用户在旧 Bourne sh shell 中运行它,则读取和条件 [[ 将失败但脚本将继续而不退出 -也许不想要你想要的 - 因此积极的版本更安全 这样的构造怎么样:[[ $REPLY =~ ^[Yy]$ ]] || exit -1 旧外壳如何评估它? 只是指出 - 一个新手错误,在测试时忘记顶部的 hashbang 会引发错误。确保将 #!/usr/bin/env bash(或类似的有效 hashbang)添加到脚本的顶部【参考方案2】:
[[ -f ./$sname ]] && read -p "File exists. Are you sure? " -n 1

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

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

【讨论】:

【参考方案3】:

这样你得到'y''yes'或'Enter'

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

如果你使用的是 zsh,试试这个:

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

【讨论】:

不接受默认 Y 默认 Y if [[ $response =~ ^(yes|y| ) ]] | [-z $响应];那么 在正则表达式中,不需要同时匹配yes和y,只要y开头就足够了。此外,如果默认需要为否,那么以下内容会有所帮助。阅读“响应?你确定吗?[Y/n]” && if [[ “$response” =~ ^[Yy] ]];然后回显“是的,你做到了。”; else echo "不,九死一生";菲【参考方案4】:

试试read shell 内置:

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

【讨论】:

【参考方案5】:

用例/esac。

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

优点:

    更整洁 可以更轻松地使用“OR”条件 可以使用字符范围,例如 [yY][eE][sS] 来接受单词“yes”,其中任何字符可以是小写或大写。

【讨论】:

很好的解决方案。就个人而言,如果 bash 脚本真的很糟糕,我喜欢让对方输入“是”。 当输入为否(可能是echo "Quitting script."; exit;;)时如何使用它退出,但如果输入为是,脚本将继续处理esac之后的任何内容? 如果你这样做n|N ) echo "no"; return;;,如果你说'n',脚本将在那里结束,否则继续其余的,这就是你的意思吗? @SiegeX 如果它真的非常严重,你可以让用户输入“快速棕色狐狸跳过懒狗”:P 当用户输入无效时,如何要求用户重新输入。并做'return;'如果 3 次无效。【参考方案6】:

这是我使用的函数:

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

还有一个使用它的例子:

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”工作。

希望你喜欢, 干杯!

【讨论】:

【参考方案7】:

这是我在其他地方找到的,有更好的版本吗?

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

【讨论】:

【参考方案8】:
#!/bin/bash
echo Please, enter your name
read NAME
echo "Hi $NAME!"
if [ "x$NAME" = "xyes" ] ; then
 # do something
fi

我是一个简短的脚本,用于读取 bash 并回显结果。

【讨论】:

【参考方案9】:
echo are you sure?
read x
if [ "$x" = "yes" ]
then
  # do the dangerous stuff
fi

【讨论】:

【参考方案10】:

qnd:使用

read VARNAME
echo $VARNAME

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

【讨论】:

以上是关于如何在 bash 脚本中提示用户进行确认? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 bash 中进行 while 循环工作?

如何在 bash 中获取通过 $PATH 执行的脚本的绝对路径? [复制]

如何从 bash 脚本中 ssh?

如何在 bash 脚本中捕获 mysqldump 错误? [复制]

Bash脚本练习(欢迎提意见,共同学习)

如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? [复制]