Dans Bash, comment ajouter "Are you sure [Y/ n]" à une commande ou un alias?
dans ce cas précis, j'aimerais ajouter une confirmation à Bash pour
Are you sure? [Y/n]
pour hg push ssh://username@www.example.com//somepath/morepath
de Mercurial, qui est en fait un alias. Y a-t-il une commande standard qui peut être ajoutée à l'alias pour la réaliser?
la raison est que hg push
et hg out
peuvent sembler similaires et parfois quand je veux hgoutrepo
, je peux accidentellement taper hgpushrepo
(les deux sont des alias).
Mise à jour: si cela peut être quelque chose comme une commande intégrée avec une autre commande, comme: confirm && hg push ssh://...
ce serait génial... juste une commande qui peut demander un yes
ou no
et continuer avec le reste si yes
.
16 réponses
ce sont des formes plus compactes et polyvalentes de Hamish réponse . Ils manipulent n'importe quel mélange de lettres majuscules et minuscules:
read -r -p "Are you sure? [y/N] " response
case "$response" in
[yY][eE][sS]|[yY])
do_something
;;
*)
do_something_else
;;
esac
Ou, pour Bash >= version 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: Si $response
est une chaîne vide, cela donnera une erreur. Pour corriger, il suffit d'ajouter des guillemets: "$response"
. - Toujours utiliser des guillemets doubles dans les variables contenant des chaînes (par exemple: prefer pour utiliser "$@"
au lieu de $@
).
Ou, Bash 4.x:
read -r -p "Are you sure? [y/N] " response
response=${response,,} # tolower
if [[ "$response" =~ ^(yes|y)$ ]]
...
Edit:
en réponse à votre édition, voici comment vous créeriez et utiliseriez une commande confirm
basée sur la première version de ma réponse (cela fonctionnerait de la même façon avec les deux autres):
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
}
pour utiliser cette fonction:
confirm && hg push ssh://..
ou
confirm "Would you really like to do a push?" && hg push ssh://..
voici à peu près un extrait que vous voulez. Permettez-moi de trouver comment transférer les 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
attention à yes | command name here
:)
pour éviter de vérifier explicitement ces variantes de "oui" , vous pouvez utiliser l'opérateur d'expression régulière bash '= ~ 'avec une expression régulière:
read -p "Are you sure you want to continue? <y/N> " prompt
if [[ $prompt =~ [yY](es)* ]]
then
(etc...)
qui teste si l'entrée de l'utilisateur commence par 'y' ou 'Y' et est suivie de zéro ou plus 'es.
sont facilement contournées avec les retours de chariot, et je trouve utile de demander continuellement des entrées valides.
Voici une fonction pour rendre cela facile. "input invalide" apparaît en rouge Si O|N n'est pas reçu, et l'utilisateur est invité à nouveau.
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
vous pouvez modifier l'invite par défaut en passant un argument
C'est peut-être un piratage:
comme dans la question dans Unix / Bash, "xargs-p" est-il un bon moyen de demander une confirmation avant d'exécuter une commande?
nous pouvons utiliser xargs
pour faire le travail:
echo ssh://username@www.example.com//somepath/morepath | xargs -p hg push
bien sûr, ce sera défini comme un alias, comme hgpushrepo
exemple:
$ 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
$
ajoutez ce qui suit à votre fichier/etc / bashrc. Ce script ajoute une "fonction" résidente au lieu d'un alias appelé "confirmer".
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
}
read -r -p "Are you sure? [Y/n]" response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
your-action-here
fi
Eh bien, voici ma version de confirm
, modifiée de celle de James:
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
}
ces modifications sont:
- utiliser
local
pour empêcher les noms de variables de se heurter -
read
utilisez...
pour contrôler son action, vous pouvez donc utiliser-n
et-t
- si
read
les sorties sans succès,echo
une ligne d'alimentation de la beauté - mon
Git on Windows
seulement abash-3.1
et n'a "aucune 1519110920" oufalse
, afin de l'utiliserreturn
à la place. Bien sûr, cela est aussi compatible avec bash-4.4 (l'actuel en Git pour Windows). - utilisez le style IPython (y / [n]) "pour indiquer clairement que" n " est la valeur par défaut.
en retard au jeu, mais j'ai créé encore une autre variante des fonctions confirm
des réponses précédentes:
confirm ()
{
read -r -p "$(echo $@) ? [y/N] " YESNO
if [ "$YESNO" != "y" ]; then
echo >&2 "Aborting"
exit 1
fi
CMD=""
shift
while [ -n "" ]; do
echo -en ""151900920""
shift
done | xargs -0 "$CMD" || exit $?
}
Pour l'utiliser:
confirm your_command
Dispose:
- imprime votre commande dans le prompt
- passe les arguments en utilisant le délimiteur NULL
- préserve l'état de sortie de votre commande
Bugs:
-
echo -en
travaille avecbash
, mais peut échouer dans votre shell - peut échouer si les arguments interfèrent avec
echo
ouxargs
- un zillion d'autres bogues parce que les scripts shell sont durs
Essayer", 151920920"
#!/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"
Pas en appuyant sur entrée requis
Voici une approche plus longue, mais réutilisable et modulaire:
- Renvoie
0
=oui et1
=pas de - pas de pression entrée requise - un seul caractère
- peut appuyer sur entrer pour accepter le choix par défaut
- peut désactiver le choix par défaut pour forcer une sélection
- Fonctionne pour les deux
zsh
etbash
.
défaut à "non" en appuyant sur Entrée
notez que le N
est capitalisé. Ici enter est pressé, en acceptant la valeur par défaut:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?
note également que [y/N]?
a été automatiquement ajouté.
Le "non" par défaut est accepté, donc rien n'est repris.
re-prompt jusqu'à ce qu'une réponse valide soit donnée:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *
défaut à "Oui" en appuyant sur Entrée
notez que le Y
est capitalisé:
$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *
ci-dessus, j'ai juste appuyé sur Entrée, donc la commande a couru.
Pas de défaut sur entrée - besoin de y
ou n
$ 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
Ici, 1
ou false est retourné. Pas de capitalisation dans [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
}
ce n'est pas exactement une" demande pour oui ou non "mais juste un piratage: alias le hg push ...
pas à hgpushrepo
mais à hgpushrepoconfirmedpush
et au moment où je peux épeler toute la chose, le cerveau gauche a fait un choix logique.
pas la même chose, mais l'idée qui fonctionne de toute façon.
#!/bin/bash
i='y'
while [ ${i:0:1} != n ]
do
# Command(s)
read -p " Again? Y/n " i
[[ ${#i} -eq 0 ]] && i='y'
done
sortie:
Encore? O / n N
Encore? O / n Anything
Encore? O / n 7
Encore? Y / n &
Encore? O / n nsijf
$ 151920920"
ne vérifie maintenant que le 1er caractère de $que j'ai lu.
le code ci-dessous combine deux choses
-
shopt -s nocasematch qui prendra en charge la casse
-
et si la condition qui accepte à la fois l'entrée soit vous passez oui,Oui,OUI,y'.
shopt-s nocasematch
si [[ sed-4.2.2.$LIGNE =~ (oui|y)$ ]]
puis sortie 0
fi
voici ma solution qui utilise regex localisé. Donc en allemand aussi "j "Pour" Ja " serait interprété comme Oui.
le premier argument est la question, si le deuxième argument est" y " que oui serait la réponse par défaut sinon non serait la réponse par défaut. La valeur de retour est 0 si la réponse est "oui" et 1 si la réponse est "non".
function shure(){
if [ $# -gt 1 ] && [[ "" =~ ^[yY]*$ ]] ; then
arg="[Y/n]"
reg=$(locale noexpr)
default=(0 1)
else
arg="[y/N]"
reg=$(locale yesexpr)
default=(1 0)
fi
read -p " ${arg}? : " answer
[[ "$answer" =~ $reg ]] && return ${default[1]} || return ${default[0]}
}
Voici une utilisation de base
# 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]? : "
C'est peut-être un peu trop court, mais pour mon usage privé, il fonctionne très bien
read -n 1 -p "Push master upstream? [Y/n] " reply;
if [ "$reply" != "" ]; then echo; fi
if [ "$reply" != "n" ]; then
git push upstream master
fi
le read -n 1
ne lit qu'un caractère. Si ce n'est pas un " n "minuscule, on suppose que c'est un "Y".
(comme pour la vraie question: faire qu'un script bash et changer votre alias pour pointer vers ce script au lieu de ce qui pointait vers avant)