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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1885525/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:46:30  来源:igfitidea点击:

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

bash

提问by Tom

I want to put a quick "are you sure?" prompt for confirmation at the top of a potentially dangerous bash script, what's the easiest/best way to do this?

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

回答by Paused until further notice.

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

I incorporated levislevis85's suggestion (thanks!) and added the -noption to readto accept one character without the need to press Enter. You can use one or both of these.

我股份有限公司levislevis85的建议(感谢!),并添加-n选项,以read接受,而不需要按一个字符Enter。您可以使用其中一种或两种。

Also, the negated form might look like this:

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

read -p "Are you sure? " -n 1 -r
echo    # (optional) move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
    [[ "
read -p "Continue (y/n)?" choice
case "$choice" in 
  y|Y ) echo "yes";;
  n|N ) echo "no";;
  * ) echo "invalid";;
esac
" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell fi

However, as pointed out by Erich, under some circumstances such as a syntax error caused by the script being run in the wrong shell, the negated form could allow the script to continue to the "dangerous stuff". The failure mode should favor the safest outcome so only the first, non-negated ifshould be used.

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

Explanation:

解释:

The readcommand outputs the prompt (-p "prompt") then accepts one character (-n 1) and accepts backslashes literally (-r) (otherwise readwould see the backslash as an escape and wait for a second character). The default variable for readto store the result in is $REPLYif you don't supply a name like this: read -p "my prompt" -n 1 -r my_var

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

The ifstatement uses a regular expression to check if the character in $REPLYmatches (=~) an upper or lower case "Y". The regular expression used here says "a string starting (^) and consisting solely of one of a list of characters in a bracket expression ([Yy]) and ending ($)". The anchors (^and $) prevent matching longer strings. In this case they help reinforce the one-character limit set in the readcommand.

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

The negated form uses the logical "not" operator (!) to match (=~) any character that is not "Y" or "y". An alternative way to express this is less readable and doesn't as clearly express the intent in my opinion in this instance. However, this is what it would look like: if [[ $REPLY =~ ^[^Yy]$ ]]

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

回答by ghostdog74

use case/esac.

用例/esac。

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

advantage:

优势:

  1. neater
  2. can use "OR" condition easier
  3. can use character range, eg [yY][eE][sS] to accept word "yes", where any of its characters may be in lowercase or in uppercase.
  1. 更整洁
  2. 可以更容易地使用“OR”条件
  3. 可以使用字符范围,例如 [yY][eE][sS] 来接受单词“yes”,其中任何字符都可以是小写或大写。

回答by Adam Hupp

Try the readshell builtin:

尝试read内置的shell:

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

回答by SergioAraujo

This way you get 'y' 'yes' or 'Enter'

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

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

If you are using zsh try this:

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

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

回答by Sébastien RoccaSerra

Here's the function I use :

这是我使用的功能:

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...

And an example using it:

以及使用它的示例:

read -p "Are you sure you wish to continue?"
if [ "$REPLY" != "yes" ]; then
   exit
fi
  • The output is always "yes" or "no"
  • It's "no" by default
  • Everything except "y" or "yes" returns "no", so it's pretty safe for a dangerous bash script
  • And it's case insensitive, "Y", "Yes", or "YES" work as "yes".
  • 输出总是“是”或“否”
  • 默认为“否”
  • 除“y”或“yes”之外的所有内容都返回“no”,因此对于危险的 bash 脚本来说非常安全
  • 它不区分大小写,“Y”、“是”或“是”作为“是”工作。

I hope you like it,
Cheers!

我希望你喜欢它,
干杯!

回答by Tom

This what I found elsewhere, is there a better possible version?

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

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

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

回答by Bradley

#!/bin/bash
echo Please, enter your name
read NAME
echo "Hi $NAME!"
if [ "x$NAME" = "xyes" ] ; then
 # do something
fi

used this in a function to look for an existing file and prompt before overwriting.

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

回答by Philip Schlump

read VARNAME
echo $VARNAME

I s a short script to read in bash and echo back results.

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

回答by zen

qnd: use

qnd:使用

echo are you sure?
read x
if [ "$x" = "yes" ]
then
  # do the dangerous stuff
fi

for a one line response without readline support. Then test $VARNAME however you want.

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

回答by kingsindian

##代码##