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 .

178
demandé sur 太極者無極而生 2010-07-12 23:58:32

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://..
269
répondu Dennis Williamson 2017-09-19 13:29:29

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 :)

19
répondu Hamish Grubijan 2010-07-12 20:04:12

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.

10
répondu user389850 2010-07-12 20:33:23
Les Confirmations

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

7
répondu briceburg 2015-09-22 04:00:25

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

$
4
répondu 太極者無極而生 2017-05-23 12:02:51

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
}
3
répondu MattyV 2010-07-16 18:30:35
read -r -p "Are you sure? [Y/n]" response
  response=${response,,} # tolower
  if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
      your-action-here
  fi
3
répondu SergioAraujo 2017-07-26 14:03:00

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:

  1. utiliser local pour empêcher les noms de variables de se heurter
  2. read utilisez ... pour contrôler son action, vous pouvez donc utiliser -n et -t
  3. si read les sorties sans succès, echo une ligne d'alimentation de la beauté
  4. mon Git on Windows seulement a bash-3.1 et n'a "aucune 1519110920" ou false , afin de l'utiliser return à la place. Bien sûr, cela est aussi compatible avec bash-4.4 (l'actuel en Git pour Windows).
  5. utilisez le style IPython (y / [n]) "pour indiquer clairement que" n " est la valeur par défaut.
2
répondu Dahan Gong 2018-01-26 06:19:33

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 avec bash , mais peut échouer dans votre shell
  • peut échouer si les arguments interfèrent avec echo ou xargs
  • un zillion d'autres bogues parce que les scripts shell sont durs
1
répondu thomas.me 2013-02-02 01:52:40

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"
1
répondu Ranjithkumar T 2016-04-05 09:15:30

Pas en appuyant sur entrée requis

Voici une approche plus longue, mais réutilisable et modulaire:

  • Renvoie 0 =oui et 1 =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 et bash .

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
}
1
répondu Tom Hale 2018-06-28 06:50:26

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.

0
répondu 太極者無極而生 2010-07-13 21:36:53

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.

0
répondu anonimous 2015-12-02 06:31:46

le code ci-dessous combine deux choses

  1. shopt -s nocasematch qui prendra en charge la casse

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

0
répondu Shyam Gupta 2017-09-30 14:21:43

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]? : "
0
répondu David Boho 2017-11-09 09:20:14

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)

0
répondu commonpike 2018-04-11 14:14:23