在 Bash 中,如何将“Are you sure [Y/n]”添加到任何命令或别名?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3231804/
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 19:27:08  来源:igfitidea点击:

In Bash, how to add "Are you sure [Y/n]" to any command or alias?

bashaliasconfirmation

提问by nonopolarity

In this particular case, I'd like to add a confirm in Bash for

在这种特殊情况下,我想在 Bash 中添加一个确认

Are you sure? [Y/n]

for Mercurial's hg push ssh://[email protected]//somepath/morepath, which is actually an alias. Is there a standard command that can be added to the alias to achieve it?

对于 Mercurial 的hg push ssh://[email protected]//somepath/morepath,它实际上是一个别名。是否有标准命令可以添加到别名中以实现它?

The reason is that hg pushand hg outcan sound similar and sometimes when I want hgoutrepo, I may accidentlly type hgpushrepo(both are aliases).

原因是hg pushhg out听起来很相似,有时当我想要时hgoutrepo,我可能会不小心输入hgpushrepo(两者都是别名)。

Update:if it can be something like a built-in command with another command, such as: confirm && hg push ssh://...that'd be great... just a command that can ask for a yesor noand continue with the rest if yes.

更新:如果它可以是带有另一个命令的内置命令,例如:confirm && hg push ssh://...那就太好了......只是一个可以要求 a yesorno并继续其余 if 的命令yes

回答by Paused until further notice.

These are more compact and versatile forms of Hamish'sanswer. They handle any mixture of upper and lower case letters:

这些是Hamish'sanswer 的更紧凑和更通用的形式。它们处理大小写字母的任何混合:

read -r -p "Are you sure? [y/N] " response
case "$response" in
    [yY][eE][sS]|[yY]) 
        do_something
        ;;
    *)
        do_something_else
        ;;
esac

Or, for Bash >= version 3.2:

或者,对于 Bash >= 3.2 版:

read -r -p "Are you sure? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
then
    do_something
else
    do_something_else
fi

Note: If $responseis an empty string, it will give an error. To fix, simply add quotation marks: "$response". – Always use double quotes in variables containing strings (e.g.: prefer to use "$@"instead $@).

注意:如果$response是空字符串,则会报错。要修复,只需添加引号:"$response". -始终包含字符串变量用双引号(如:喜欢使用"$@"代替$@)。

Or, Bash 4.x:

或者,Bash 4.x:

read -r -p "Are you sure? [y/N] " response
response=${response,,}    # tolower
if [[ "$response" =~ ^(yes|y)$ ]]
...

Edit:

编辑:

In response to your edit, here's how you'd create and use a confirmcommand based on the first version in my answer (it would work similarly with the other two):

为了响应您的编辑,以下是您将如何confirm根据我的答案中的第一个版本创建和使用命令(它与其他两个版本类似):

confirm() {
    # call with a prompt string or use a default
    read -r -p "${1:-Are you sure? [y/N]} " response
    case "$response" in
        [yY][eE][sS]|[yY]) 
            true
            ;;
        *)
            false
            ;;
    esac
}

To use this function:

要使用此功能:

confirm && hg push ssh://..

or

或者

confirm "Would you really like to do a push?" && hg push ssh://..

回答by Hamish Grubijan

Here is roughly a snippet that you want. Let me find out how to forward the arguments.

这是您想要的大致片段。让我找出如何转发论点。

read -p "Are you sure you want to continue? <y/N> " prompt
if [[ $prompt == "y" || $prompt == "Y" || $prompt == "yes" || $prompt == "Yes" ]]
then
  # http://stackoverflow.com/questions/1537673/how-do-i-forward-parameters-to-other-command-in-bash-script
else
  exit 0
fi

Watch out for yes | command name here:)

当心yes | command name here:)

回答by briceburg

Confirmations are easily bypassed with carriage returns, and I find it useful to continually prompt for valid input.

回车很容易绕过确认,我发现不断提示输入有效信息很有用。

Here's a function to make this easy. "invalid input" appears in red if Y|N is not received, and the user is prompted again.

这是一个使这变得容易的函数。如果没有收到Y|N,“无效输入”显示为红色,再次提示用户。

prompt_confirm() {
  while true; do
    read -r -n 1 -p "${1:-Continue?} [y/n]: " REPLY
    case $REPLY in
      [yY]) echo ; return 0 ;;
      [nN]) echo ; return 1 ;;
      *) printf " 3[31m %s \n3[0m" "invalid input"
    esac 
  done  
}

# example usage
prompt_confirm "Overwrite File?" || exit 0

You can change the default prompt by passing an argument

您可以通过传递参数来更改默认提示

回答by user389850

To avoid explicitly checking for these variants of 'yes' you could use the bash regular expression operator '=~' with a regular expression:

为了避免显式检查 'yes' 的这些变体,您可以将 bash 正则表达式运算符 '=~' 与正则表达式一起使用:

read -p "Are you sure you want to continue? <y/N> " prompt
if [[ $prompt =~ [yY](es)* ]]
then
(etc...)

That tests whether the user input starts with 'y' or 'Y' and is followed by zero or more 'es's.

这将测试用户输入是否以“y”或“Y”开头,并后跟零个或多个“es”。

回答by nonopolarity

This may be a hack:

这可能是一个黑客:

as in question In Unix / Bash, is "xargs -p" a good way to prompt for confirmation before running any command?

如问题在Unix / Bash中,“xargs -p”是在运行任何命令之前提示确认的好方法吗?

we can using xargsto do the job:

我们可以xargs用来完成这项工作:

echo ssh://[email protected]//somepath/morepath | xargs -p hg push

of course, this will be set as an alias, like hgpushrepo

当然,这将被设置为别名,例如 hgpushrepo

Example:

例子:

$ echo foo | xargs -p ls -l
ls -l foo?...y
-rw-r--r--  1 mikelee    staff  0 Nov 23 10:38 foo

$ echo foo | xargs -p ls -l
ls -l foo?...n

$

回答by MattyV

Add the following to your /etc/bashrc file. This script adds a resident "function" instead of an alias called "confirm".

将以下内容添加到您的 /etc/bashrc 文件中。该脚本添加了一个常驻“函数”,而不是一个名为“确认”的别名。



function confirm( )
{
#alert the user what they are about to do.
echo "About to $@....";
#confirm with the user
read -r -p "Are you sure? [Y/n]" response
case "$response" in
    [yY][eE][sS]|[yY]) 
              #if yes, then execute the passed parameters
               "$@"
               ;;
    *)
              #Otherwise exit...
              echo "ciao..."
              exit
              ;;
esac
}

回答by commonpike

This may be a little too short, but for my own private use, it works great

这可能有点太短了,但对于我自己的私人使用来说,效果很好

read -n 1 -p "Push master upstream? [Y/n] " reply; 
if [ "$reply" != "" ]; then echo; fi
if [ "$reply" = "${reply#[Nn]}" ]; then
    git push upstream master
fi

The read -n 1just reads one character. No need to hit enter. If it's not a 'n' or 'N', it is assumed to be a 'Y'. Just pressing enter means Y too.

read -n 1只读取一个字符。无需按回车键。如果它不是“n”或“N”,则假定它是“Y”。只需按 Enter 也意味着 Y。

(as for the real question: make that a bash script and change your alias to point to that script instead of what is was pointing to before)

(至于真正的问题:将其设为 bash 脚本并将别名更改为指向该脚本而不是之前指向的内容)

回答by SergioAraujo

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

回答by Tom Hale

No pressing enter required

无需按回车键

Here's a longer, but reusable and modular approach:

这是一个更长但可重用的模块化方法:

  • Returns 0=yes and 1=no
  • No pressing enter required - just a single character
  • Can press enterto accept the default choice
  • Can disable default choice to force a selection
  • Works for both zshand bash.
  • 返回0=yes 和1=no
  • 无需按 Enter - 只需一个字符
  • 可以按enter接受默认选择
  • 可以禁用默认选择以强制选择
  • 适用于zshbash

Defaulting to "no" when pressing enter

按 Enter 时默认为“no”

Note that the Nis capitalsed. Here enter is pressed, accepting the default:

请注意,N是大写的。这里按下回车,接受默认值:

$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?

Also note, that [y/N]?was automatically appended. The default "no" is accepted, so nothing is echoed.

另请注意,这[y/N]?是自动附加的。接受默认的“no”,所以没有回显。

Re-prompt until a valid response is given:

重新提示直到给出有效响应:

$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *

Defaulting to "yes" when pressing enter

按回车时默认为“是”

Note that the Yis capitalised:

请注意,Y大写:

$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *

Above, I just pressed enter, so the command ran.

在上面,我只是按了 Enter,所以命令就运行了。

No default on enter- require yor n

没有默认值enter- 需要yn

$ get_yes_keypress "Here you cannot press enter. Do you like this"
Here you cannot press enter. Do you like this [y/n]? k
Here you cannot press enter. Do you like this [y/n]?
Here you cannot press enter. Do you like this [y/n]? n
$ echo $?
1

Here, 1or false was returned. Note no capitalisation in [y/n]?

在这里,1或返回 false。注意没有大写[y/n]?

Code

代码

# Read a single char from /dev/tty, prompting with "$*"
# Note: pressing enter will return a null string. Perhaps a version terminated with X and then remove it in caller?
# See https://unix.stackexchange.com/a/367880/143394 for dealing with multi-byte, etc.
function get_keypress {
  local REPLY IFS=
  >/dev/tty printf '%s' "$*"
  [[ $ZSH_VERSION ]] && read -rk1  # Use -u0 to read from STDIN
  # See https://unix.stackexchange.com/q/383197/143394 regarding '\n' -> ''
  [[ $BASH_VERSION ]] && </dev/tty read -rn1
  printf '%s' "$REPLY"
}

# Get a y/n from the user, return yes=0, no=1 enter=
# Prompt using .
# If set, return  on pressing enter, useful for cancel or defualting
function get_yes_keypress {
  local prompt="${1:-Are you sure} [y/n]? "
  local enter_return=
  local REPLY
  # [[ ! $prompt ]] && prompt="[y/n]? "
  while REPLY=$(get_keypress "$prompt"); do
    [[ $REPLY ]] && printf '\n' # $REPLY blank if user presses enter
    case "$REPLY" in
      Y|y)  return 0;;
      N|n)  return 1;;
      '')   [[ $enter_return ]] && return "$enter_return"
    esac
  done
}

# Credit: http://unix.stackexchange.com/a/14444/143394
# Prompt to confirm, defaulting to NO on <enter>
# Usage: confirm "Dangerous. Are you sure?" && rm *
function confirm {
  local prompt="${*:-Are you sure} [y/N]? "
  get_yes_keypress "$prompt" 1
}    

# Prompt to confirm, defaulting to YES on <enter>
function confirm_yes {
  local prompt="${*:-Are you sure} [Y/n]? "
  get_yes_keypress "$prompt" 0
}

回答by jasonleonhard

This version allows you to have more than one case yor Y, nor N

此版本允许您拥有多个 caseyY,nN

  1. Optionally: Repeat the question until an approve question is provided

  2. Optionally: Ignore any other answer

  3. Optionally: Exit the terminal if you want

    confirm() {
        echo -n "Continue? y or n? "
        read REPLY
        case $REPLY in
        [Yy]) echo 'yup y' ;; # you can change what you do here for instance
        [Nn]) break ;;        # exit case statement gracefully
        # Here are a few optional options to choose between
        # Any other answer:
    
        # 1. Repeat the question
        *) confirm ;;
    
        # 2. ignore
        # *) ;;
    
        # 3. Exit terminal
        # *) exit ;;
    
        esac
        # REPLY=''
    }
    
  1. 可选:重复问题,直到提供批准问题

  2. 可选:忽略任何其他答案

  3. 可选:如果需要,退出终端

    confirm() {
        echo -n "Continue? y or n? "
        read REPLY
        case $REPLY in
        [Yy]) echo 'yup y' ;; # you can change what you do here for instance
        [Nn]) break ;;        # exit case statement gracefully
        # Here are a few optional options to choose between
        # Any other answer:
    
        # 1. Repeat the question
        *) confirm ;;
    
        # 2. ignore
        # *) ;;
    
        # 3. Exit terminal
        # *) exit ;;
    
        esac
        # REPLY=''
    }
    

Notice this too: On the last line of this function clear the REPLY variable. Otherwise if you echo $REPLYyou will see it is still set until you open or close your terminal or set it again.

还要注意这一点:在此函数的最后一行清除 REPLY 变量。否则,如果您echo $REPLY会看到它仍然设置,直到您打开或关闭终端或再次设置它。