如何在 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 中获取通过 $PATH 执行的脚本的绝对路径? [复制]