In Bash, how to add “Are you sure [Y/n]” to any command or alias?
在这个特殊情况下,我想在bash中添加一个确认
1 | Are you sure? [Y/n] |
对于Mercurial的
原因是
更新:如果它可以像一个内置命令和另一个命令,例如:
这些都是哈米什答案的更紧凑和更广泛的形式。它们处理任何大小写字母的混合:
1 2 3 4 5 6 7 8 9 | read -r -p"Are you sure? [y/N]" response case"$response" in [yY][eE][sS]|[yY]) do_something ;; *) do_something_else ;; esac |
或者,对于bash>=3.2版:
1 2 3 4 5 6 7 | read -r -p"Are you sure? [y/N]" response if [["$response" =~ ^([yY][eE][sS]|[yY])+$ ]] then do_something else do_something_else fi |
注:如果
或者,BASH 4。
1 2 3 4 | read -r -p"Are you sure? [y/N]" response response=${response,,} # tolower if [["$response" =~ ^(yes|y)$ ]] ... |
编辑:
为了响应您的编辑,下面介绍如何根据我的答案中的第一个版本创建和使用
1 2 3 4 5 6 7 8 9 10 11 12 | 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 } |
要使用此功能:
1 | confirm && hg push ssh://.. |
或
1 | confirm"Would you really like to do a push?" && hg push ssh://.. |
这大概是你想要的一个片段。我来看看如何提出论点。
1 2 3 4 5 6 7 | 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 |
当心
为了避免显式地检查这些变量"yes",可以将bash正则表达式运算符"=~"与正则表达式一起使用:
1 2 3 4 | read -p"Are you sure you want to continue? <y/N>" prompt if [[ $prompt =~ [yY](es)* ]] then (etc...) |
它测试用户输入是以"y"还是"y"开头,后跟零个或多个"es"。
确认很容易通过回车绕过,我发现持续提示有效输入很有用。
这是一个简单的功能。"如果未收到Y N,则"无效输入"显示为红色,并再次提示用户。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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" \033[31m %s \033[0m""invalid input" esac done } # example usage prompt_confirm"Overwrite File?" || exit 0 |
可以通过传递参数来更改默认提示
这可能是一个黑客:
正如在UNIX/bash中所讨论的,"xargs-p"是在运行任何命令之前提示确认的一种好方法吗?
我们可以用
1 | echo ssh://username@www.example.com//somepath/morepath | xargs -p hg push |
当然,这将被设置为别名,如
例子:
1 2 3 4 5 6 7 8 | $ 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 $ |
将以下内容添加到/etc/bashrc文件中。这个脚本添加了一个常驻的"函数",而不是一个名为"确认"的别名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 } |
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 |
好吧,这是我的版本的
1 2 3 4 5 6 7 8 | function confirm() { local response msg="${1:-Are you sure} (y/[n])?"; shift read -r $* -p"$msg" response || echo case"$response" in [yY][eE][sS]|[yY]) return 0 ;; *) return 1 ;; esac } |
这些变化包括:
尝试,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/bash pause () { REPLY=Y while ["$REPLY" =="Y" ] || ["$REPLY" !="y" ] do echo -e"\t\tPress 'y' to continue\t\t\tPress 'n' to quit" read -n1 -s case"$REPLY" in "n") exit ;; "N") echo"case sensitive!!" ;; "y") clear ;; "Y") echo"case sensitive!!" ;; * ) echo"$REPLY is Invalid Option" ;; esac done } pause echo"Hi" |
不需要按Enter键
这里有一个较长但可重用的模块化方法:
- 返回
0 是,1 否 - 不需要按Enter键-只需要一个字符
- 可以按enter接受默认选项
- 可以禁用默认选项以强制选择
- 适用于
zsh 和bash 。
按Enter时默认为"否"
注意,
1 2 | $ confirm"Show dangerous command" && echo"rm *" Show dangerous command [y/N]? |
另请注意,
重新提示直到给出有效响应:
1 2 3 4 | $ confirm"Show dangerous command" && echo"rm *" Show dangerous command [y/N]? X Show dangerous command [y/N]? y rm * |
按Enter时默认为"是"
注意,
1 2 3 | $ confirm_yes"Show dangerous command" && echo"rm *" Show dangerous command [Y/n]? rm * |
上面,我刚按下Enter,命令就运行了。
enter无违约-需要1 2 3 4 5 6 | $ 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 |
在这里,返回了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | # 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 ' ' -> '' [[ $BASH_VERSION ]] && </dev/tty read -rn1 printf '%s'"$REPLY" } # Get a y/n from the user, return yes=0, no=1 enter=$2 # Prompt using $1. # If set, return $2 on pressing enter, useful for cancel or defualting function get_yes_keypress { local prompt="${1:-Are you sure} [y/n]?" local enter_return=$2 local REPLY # [[ ! $prompt ]] && prompt="[y/n]?" while REPLY=$(get_keypress"$prompt"); do [[ $REPLY ]] && printf ' ' # $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 } |
游戏后期,但我又创造了另一个版本的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | confirm () { read -r -p"$(echo $@) ? [y/N]" YESNO if ["$YESNO" !="y" ]; then echo >&2"Aborting" exit 1 fi CMD="$1" shift while [ -n"$1" ]; do echo -en"$1\0" shift done | xargs -0"$CMD" || exit $? } |
使用它:
1 | confirm your_command |
特征:
- 作为提示的一部分打印命令
- 使用空分隔符传递参数
- 保留命令的退出状态
漏洞:
echo -en 与bash 一起工作,但可能在你的外壳中失败。- 如果论据干扰
echo 或xargs 可能会失败。 - 因为shell脚本编写很难
不一样,但无论如何都有效的想法。
1 2 3 4 5 6 7 8 | #!/bin/bash i='y' while [ ${i:0:1} != n ] do # Command(s) read -p" Again? Y/n" i [[ ${#i} -eq 0 ]] && i='y' done |
输出:再一次?y/n n再一次?任何东西再一次?Y/N 7再一次?Y/N/AMP;再一次?Y/N-NSIJF$
现在只检查我读到的$1的第一个字符。
这不是一个"问是还是不"的说法,而是一个黑客行为:把
下面的代码结合了两件事
Shopt-s NocaseMatch将处理不区分大小写的问题
如果条件同时接受这两个输入,那么您要么通过Yes,Yes,Yes,Y。
购物-S nocasemach
如果[[SED-4.2.2.$line=~(是Y)$]
然后退出0
FI
这是我使用本地化regex的解决方案。所以在德语中,"ja"的"j"也可以理解为"是"。
第一个参数是问题,如果第二个参数是"y",则默认答案为"yes",否则默认答案为"no"。如果答案为"是",则返回值为0;如果答案为"否",则返回值为1。
1 2 3 4 5 6 7 8 9 10 11 12 13 | function shure(){ if [ $# -gt 1 ] && [["$2" =~ ^[yY]*$ ]] ; then arg="[Y/n]" reg=$(locale noexpr) default=(0 1) else arg="[y/N]" reg=$(locale yesexpr) default=(1 0) fi read -p"$1 ${arg}? :" answer [["$answer" =~ $reg ]] && return ${default[1]} || return ${default[0]} } |
这是一个基本用法
1 2 3 4 5 6 7 | # basic example default is no shure"question message" && echo"answer yes" || echo"answer no" # print"question message [y/N]? :" # basic example default set to yes shure"question message" y && echo"answer yes" || echo"answer no" # print"question message [Y/n]? :" |
这可能有点太短了,但对我个人来说,它很管用
1 2 3 4 5 | read -n 1 -p"Push master upstream? [Y/n]" reply; if ["$reply" !="" ]; then echo; fi if ["$reply" !="n" ]; then git push upstream master fi |
(至于真正的问题:创建一个bash脚本,并更改别名以指向该脚本,而不是指向以前的脚本)