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的默认变量是$REPLY:read -p"my prompt" -n 1 -r my_var。
if语句使用正则表达式检查$REPLY中的字符是否与(=~中的字符)的大小写"y"匹配。这里使用的正则表达式表示"一个字符串,从(^开始,仅由括号表达式([Yy]和结束($中的一个字符列表组成)"。锚(^和$防止匹配较长的字符串。在这种情况下,它们有助于加强read命令中设置的一个字符限制。
否定形式使用逻辑"not"运算符(!)来匹配(=~)任何非"y"或"y"的字符。另一种表达这一点的方法可读性较低,在我看来,在这种情况下也不能如此清晰地表达意图。然而,这就是它的样子:if [[ $REPLY =~ ^[^Yy]$ ]]。
- 谢谢,双方括号有什么作用?
- 这能被否定吗?即,如果不匹配,是否退出?
- 它比[]有更多的特性,包括regex匹配操作符=~。参见:mywiki.wooledge.org/bashfaq/031
- if [[ ! $REPLY =~ [Yy] ]]
- 一个小问题。如果用户输入以y_y开头的任何内容,它将通过。[[$A=~"^[YY]$"]
- 在"读取"之后,您应该做一个"回音",让光标回到下一行。(只要一个没有参数的原始"回声"就可以了)
- 读取行应在末尾指定变量:read -p"Are you sure?" -n 1 -r REPLY。
- @调谐器:如果没有提供变量名,则自动设置$REPLY。
- @丹尼斯·威廉姆森:我的基于Cygwin的bash 4.1.10(4)在某种程度上不起作用。
- @调谐器:"不工作"不提供任何信息。请详细描述它是如何做到的,因为它应该在bash的每个版本中,从3.2到4.2,都是这样的。
- @丹尼斯威廉姆森起初不会执行if子句的内部部分。再次检查,它工作。在第一次尝试中可能有一些行尾。对不起,噪音太大了。
- 为了澄清,-r选项告诉read不要将反斜杠解释为转义字符。我知道它也可以用在上面的否定形式上。
- 只是对否定形式的警告-如果您的用户在旧的Bourne shshell中运行该命令,则存在读取和条件[将失败,但脚本将继续运行而不退出-可能不希望退出-因此,肯定版本更安全。
- @Erichbschulz:但是sh既不支持[[也不支持=~。
- @丹尼斯威廉姆森,这就是问题所在!所以,如果一个"bash"脚本在旧的shell下运行(这是可能的),那么被否定的表单就会从测试跳过出口……然后直接进入"危险物品"。
- @埃里希布舒尔茨:奇怪的是,当在sh下运行时,我得到了否定和非否定形式的[[: not found。你在运行哪个sh?哦,现在我明白你的意思了。你说的不是语法,而是逻辑。是的,你的观点非常正确!
- 那么这样的构造呢:[[ $REPLY =~ ^[Yy]$ ]] || exit -1旧的shell如何评价它呢?
- @Scolytus:在任何支持该语句所使用的所有特性的shell中都可以很好地工作:双方括号条件,$REPLY是read和regex匹配的默认变量。总之,它们由bash>=3.2、ksh 93(至少)和zsh(我不知道版本历史)支持。大多数shell版本都支持||结构(逻辑或)。
- 只是指出一个新手在测试时忘记了顶部的hashbang会抛出错误。确保添加!/usr/bin/env bash(或类似的有效hashbang)到脚本顶部
- 我能建议在fi之后插入一个echo""吗?这将把光标发送到一个新行,只是为了更好的用户体验:)在此之前,结果输出是:Are you sure? nroot@server:。
- @杰尔:这是个好建议。我已经把它加到我的答案里了。
- 剧本是做什么的?
- @德米特里:你能更具体一点吗?或者你打算把你的问题附在上面的原始问题上?
- @丹尼斯威廉姆森,我只是好奇的申请。可能不是什么好评论。
- 有人能在if语句中分解=~ ^[Yy]$所做的工作/手段吗?if [[ $REPLY =~ ^[Yy]$ ]]
- @托尼:=~是bash的regex匹配操作符。^[Yy]$是一个正则表达式,表示一个仅由大写或小写y组成的字符串。
- 如果我想要它是Y或者按Enter键呢?
- 4:@ pineappleunderthesea与狂欢,你可以在默认设置:用户会read -p"Are you sure?" -r -i y -ebut the need to to be to change the可以Backspace"Y"或"N",for an example。for the bash和3.2相变后,在模式匹配在the example to我的答案在第一^([Yy]|)$这比赛上下房屋或means to"或"Y"(空白行)。
- 你会如何答复@ denniswilliamson着色for the message?
- "愤怒的小鸟_ example:猕猴桃:yellow=$(tput setaf 3); reset=$(tput sgr0); read -p"${yellow}Name: ${reset}"EEA在彩色处理部分man 5 terminfofor the黑莓信息。注意,如果你使用read -efor You should使用Readline的支持,\001控制序列和\002to wrap yellow=$(tput setaf 3); reset=$(tput sgr0); printf -v prompt"\001${yellow}\002Name: \001${reset}\002"; read -e -p"$prompt"这样:
- 我变的条件预期二社,近=~' , if syntax error [![美元]回复~ ^ = YY元]是…哦,你如何看stackoverflow.com example is like /问题/ bash的特异性11206233 / & hellip;
- "是的,这是phpdave:bash的特异性。问题是"bash Bash和标记是在title"的问题。
- skippylegrandgourou added":一些解释。请让我知道如果我错过的东西。
- 现在,这是伟大的答案。谢谢!
使用案例/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]接受单词"是",其中任何字符可以是小写或大写。
- 良好的解决方案。personally if the bash脚本,我真的好喜欢crippling to have the person类型是收购。
- 我可以用how to this is不输入exit when the,but if(也许echo"Quitting script."; exit;;)is the the脚本将是输入,无论是在连续与一esac?
- 如果你给n|N ) echo"no"; return;;the脚本如果你有会说是N端和连续休息otherwise is that with the的意思,是你吗?
- 如果这是真的siegex @,你不能真的crippling have the user型"快速布朗福克斯jumps out over the懒惰的狗":P
- when the user is invalid投入how to the user to ask,再次输入。我的茶和回报;三是如果有错误的时代。
这样就可以得到"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 |
- 接受默认的Y not
- 如果默认为Y = [(响应元~ ^ Y是| |)] [反应] | Z,那么美元;
- 在regex there is the need to不匹配,都是Y和Y,一开始就够了。默认needs to be also,如果不好,那么下面会帮助。读取响应?你确定吗?〔〕/n y"&;&;if((""$ ^ ~ [反应] = YY);然后是"回声","恩,你其他的回声。"不,";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 |
在函数中使用此函数查找现有文件并在覆盖前提示。
- 享受"about return解析器函数,exitYou probably的意思。我喜欢你的答案,因为它是not to be if the队列indenting executed证实。
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。