it-swarm.it

Come posso chiedere l'input Sì / No / Annulla in uno script di shell Linux?

Voglio mettere in pausa l'input in uno script di Shell e Richiedere all'utente la scelta. La domanda tipo "Sì, No o Annulla" standard. Come posso realizzare questo in un tipico prompt di bash?

1273
Myrddin Emrys

Il metodo più semplice e più ampiamente disponibile per ottenere input da parte dell'utente a un prompt di shell è il comando read . Il modo migliore per illustrare il suo utilizzo è una semplice dimostrazione:

while true; do
    read -p "Do you wish to install this program?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

Un altro metodo, sottolineato da Steven Huwig, è il comando di Bash select . Ecco lo stesso esempio usando select:

echo "Do you wish to install this program?"
select yn in "Yes" "No"; do
    case $yn in
        Yes ) make install; break;;
        No ) exit;;
    esac
done

Con select non è necessario disinfettare l'input: visualizza le scelte disponibili e digita un numero corrispondente alla tua scelta. Anche cicli automaticamente, quindi non c'è bisogno di un ciclo while true per riprovare se danno input non validi.

Inoltre, si prega di consultare la risposta eccellente di F. Hauri.

1427
Myrddin Emrys

Almeno cinque risposte per una domanda generica.

A seconda di

  • posix compatibile: potrebbe funzionare su sistemi poveri con ambienti generici Shell
  • bash specifico: usando i cosiddetti bashisms

e se vuoi

  • semplice `` in linea '' domanda/risposta (soluzioni generiche)
  • interfacce abbastanza formattate, come ncurses o più grafica usando libgtk o libqt ...
  • utilizzare una potente funzionalità di cronologia readline

1. Soluzioni generiche POSIX

Potresti usare il comando read, seguito da if ... then ... else:

echo -n "Is this a good question (y/n)? "
read answer
# if echo "$answer" | grep -iq "^y" ;then
if [ "$answer" != "${answer#[Yy]}" ] ;then
    echo Yes
else
    echo No
fi

(Grazie a il commento di Adam Katz : Sostituito il test sopra con uno più portatile ed evita una forchetta :)

POSIX, ma funzione chiave singola

Ma se non vuoi che l'utente debba colpire Return, potresti scrivere:

( Modificato: Come giustamente suggerito da @JonathanLeffler, il salvataggio della configurazione di stty potrebbe essere migliore del semplice costringerli a sani di mente .)

echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
if echo "$answer" | grep -iq "^y" ;then
    echo Yes
else
    echo No
fi

Nota: Questo è stato testato sotto sh , bash , ksh , trattino e busybox !

Lo stesso, ma in attesa esplicita y o n:

#/bin/sh
echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo
answer=$( while ! head -c 1 | grep -i '[ny]' ;do true ;done )
stty $old_stty_cfg
if echo "$answer" | grep -iq "^y" ;then
    echo Yes
else
    echo No
fi

Utilizzando strumenti dedicati

Ci sono molti strumenti che sono stati creati usando libncurses, libgtk, libqt o altre librerie grafiche. Ad esempio, utilizzando whiptail:

if whiptail --yesno "Is this a good question" 20 60 ;then
    echo Yes
else
    echo No
fi

A seconda del sistema, potrebbe essere necessario sostituire whiptail con un altro strumento simile:

dialog --yesno "Is this a good question" 20 60 && echo Yes

gdialog --yesno "Is this a good question" 20 60 && echo Yes

kdialog --yesno "Is this a good question" 20 60 && echo Yes

dove 20 è l'altezza della finestra di dialogo in numero di righe e 60 è la larghezza della finestra di dialogo. Questi strumenti hanno tutti vicino alla stessa sintassi .

DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...

2. Bash specifiche soluzioni

Basic nel metodo line

read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
    y|Y )
        echo Yes
    ;;
    * )
        echo No
    ;;
esac

Preferisco usare case così ho potuto anche provare per yes | ja | si | oui se necessario ...

in linea con funzione chiave singola

Sotto bash, possiamo specificare la lunghezza dell'input previsto per il comando read:

read -n 1 -p "Is this a good question (y/n)? " answer

Sotto bash, il comando read accetta un parametro timeout , che potrebbe essere utile.

read -t 3 -n 1 -p "Is this a good question (y/n)? " answer
[ -z "$answer" ] && answer="Yes"  # if 'yes' have to be default choice

Alcuni trucchi per strumenti dedicati

Finestre di dialogo più sofisticate, oltre a semplici yes - no scopi:

dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe

Barra di avanzamento:

dialog --gauge "Filling the tank" 20 60 0 < <(
    for i in {1..100};do
        printf "XXX\n%d\n%(%a %b %T)T progress: %d\nXXX\n" $i -1 $i
        sleep .033
    done
) 

Piccola demo:

#!/bin/sh
while true ;do
    [ -x "$(which ${DIALOG%% *})" ] || DIALOG=dialog
    DIALOG=$($DIALOG --menu "Which tool for next run?" 20 60 12 2>&1 \
            whiptail       "dialog boxes from Shell scripts" >/dev/tty \
            dialog         "dialog boxes from Shell with ncurses" \
            gdialog        "dialog boxes from Shell with Gtk" \
            kdialog        "dialog boxes from Shell with Kde" ) || exit
    clear;echo "Choosed: $DIALOG."
    for i in `seq 1 100`;do
        date +"`printf "XXX\n%d\n%%a %%b %%T progress: %d\nXXX\n" $i $i`"
        sleep .0125
      done | $DIALOG --gauge "Filling the tank" 20 60 0
    $DIALOG --infobox "This is a simple info box\n\nNo action required" 20 60
    sleep 3
    if $DIALOG --yesno  "Do you like this demo?" 20 60 ;then
        AnsYesNo=Yes; else AnsYesNo=No; fi
    AnsInput=$($DIALOG --inputbox "A text:" 20 60 "Text here..." 2>&1 >/dev/tty)
    AnsPass=$($DIALOG --passwordbox "A secret:" 20 60 "First..." 2>&1 >/dev/tty)
    $DIALOG --textbox /etc/motd 20 60
    AnsCkLst=$($DIALOG --checklist "Check some..." 20 60 12 \
        Correct "This demo is useful"        off \
        Fun        "This demo is Nice"        off \
        Strong        "This demo is complex"        on 2>&1 >/dev/tty)
    AnsRadio=$($DIALOG --radiolist "I will:" 20 60 12 \
        " -1" "Downgrade this answer"        off \
        "  0" "Not do anything"                on \
        " +1" "Upgrade this anser"        off 2>&1 >/dev/tty)
    out="Your answers:\nLike: $AnsYesNo\nInput: $AnsInput\nSecret: $AnsPass"
    $DIALOG --msgbox "$out\nAttribs: $AnsCkLst\nNote: $AnsRadio" 20 60
  done

Altro campione? Dai un'occhiata a sando whiptail per scegliere il dispositivo USB e SB selettore di memoria rimovibile: USBKeyChooser

5. Usando la cronologia di readline

Esempio:

#!/bin/bash

set -i
HISTFILE=~/.myscript.history
history -c
history -r

myread() {
    read -e -p '> ' $1
    history -s ${!1}
}
trap 'history -a;exit' 0 1 2 3 6

while myread line;do
    case ${line%% *} in
        exit )  break ;;
        *    )  echo "Doing something with '$line'" ;;
      esac
  done

Questo creerà un file .myscript.history nella tua directory $HOME, che potresti usare i comandi di storia della readline, come UpDownCtrl+r e altri.

450
F. Hauri
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
340
Pistos

Puoi usare il comando built-in read ; Utilizzare l'opzione -p per Richiedere all'utente una domanda.

Da BASH4, ora puoi usare -i per suggerire una risposta, quindi l'utente deve solo premere return per inserirlo:

read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH

(Ma ricorda di usare l'opzione "readline" -e per consentire la modifica della riga con i tasti freccia)

Se vuoi una logica "si/no", puoi fare qualcosa del genere:

read -e -p "
List the content of your home dir ? [Y/n] " YN

[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
151
yPhil

Bash ha select per questo scopo.

select result in Yes No Cancel
do
    echo $result
done
102
Steven Huwig
read -p "Are you alright? (y/n) " RESP
if [ "$RESP" = "y" ]; then
  echo "Glad to hear it"
else
  echo "You need more bash programming"
fi
54
serg

Ecco qualcosa che ho messo insieme:

#!/bin/sh

promptyn () {
    while true; do
        read -p "$1 " yn
        case $yn in
            [Yy]* ) return 0;;
            [Nn]* ) return 1;;
            * ) echo "Please answer yes or no.";;
        esac
    done
}

if promptyn "is the sky blue?"; then
    echo "yes"
else
    echo "no"
fi

Sono un principiante, quindi prendilo con un pizzico di sale, ma sembra funzionare.

32
mpen
inquire ()  {
  echo  -n "$1 [y/n]? "
  read answer
  finish="-1"
  while [ "$finish" = '-1' ]
  do
    finish="1"
    if [ "$answer" = '' ];
    then
      answer=""
    else
      case $answer in
        y | Y | yes | YES ) answer="y";;
        n | N | no | NO ) answer="n";;
        *) finish="-1";
           echo -n 'Invalid response -- please reenter:';
           read answer;;
       esac
    fi
  done
}

... other stuff

inquire "Install now?"

...
28
SumoRunner

Tu vuoi:

  • Comandi incorporati di Bash (cioè portatili)
  • Controlla TTY
  • Risposta predefinita
  • Tempo scaduto
  • Domanda colorata

Frammento

do_xxxx=y                      # In batch mode => Default is Yes
[[ -t 0 ]] &&                  # If TTY => Prompt the question
read -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx  # Store the answer in $do_xxxx
if [[ $do_xxxx =~ ^(y|Y|)$ ]]  # Do if 'y' or 'Y' or empty
then
    xxxx
fi

Spiegazioni

  • [[ -t 0 ]] && read ... => Chiama il comando read se TTY
  • read -n 1 => Attendi un carattere
  • $'\e[1;32m ... \e[0m ' => Stampa in verde
    (il verde va bene perché è leggibile su entrambi gli sfondi bianco/nero)
  • [[ $do_xxxx =~ ^(y|Y|)$ ]] => bash regex

Timeout => La risposta predefinita è No

do_xxxx=y
[[ -t 0 ]] && {                   # Timeout 5 seconds (read -t 5)
read -t 5 -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx ||  # read 'fails' on timeout
do_xxxx=n ; }                     # Timeout => answer No
if [[ $do_xxxx =~ ^(y|Y|)$ ]]
then
    xxxx
fi
25
olibre

Il modo più semplice per ottenere ciò con il minor numero di righe è il seguente:

read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;

if [ "$CONDITION" == "y" ]; then
   # do something here!
fi

if è solo un esempio: sta a te decidere come gestire questa variabile.

21
Apurv Nerlekar

Usa il comando read:

echo Would you like to install? "(Y or N)"

read x

# now check if $x is "y"
if [ "$x" = "y" ]; then
    # do something here!
fi

e poi tutte le altre cose di cui hai bisogno

17
ThatLinuxGuy

Questa soluzione legge un singolo carattere e chiama una funzione su una risposta sì.

read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    do_something      
fi
17
Dennis
read -e -p "Enter your choice: " choice

L'opzione -e consente all'utente di modificare l'input utilizzando i tasti freccia.

Se vuoi utilizzare un suggerimento come input:

read -e -i "yes" -p "Enter your choice: " choice

L'opzione -i stampa un input suggestivo.

12
Jahid

Mi dispiace per la pubblicazione su un post così vecchio. Qualche settimana fa mi trovavo di fronte a un problema simile, nel mio caso avevo bisogno di una soluzione che funzionasse anche all'interno di uno script di installazione online, ad esempio: curl -Ss https://raw.github.com/_____/installer.sh | bash

Usare read yesno < /dev/tty funziona bene per me:

echo -n "These files will be uploaded. Is this ok? (y/n) "
read yesno < /dev/tty

if [ "x$yesno" = "xy" ];then

   # Yes
else

   # No
fi

Spero che questo aiuti qualcuno.

10
user1183098

Per ottenere una bella casella di input simile a ncurses usa il comando dialog in questo modo:

#!/bin/bash
if (dialog --title "Message" --yesno "Want to do something risky?" 6 25)
# message box will have the size 25x6 characters
then 
    echo "Let's do something risky"
    # do something risky
else 
    echo "Let's stay boring"
fi

Il pacchetto di dialogo è installato di default almeno con SUSE Linux.

8
Thorsten Staerk

È possibile utilizzare il REPLY predefinito su un read, convertire in lettere minuscole e confrontare con un insieme di variabili con un'espressione.
Lo script supporta anche ja/si/oui

read -rp "Do you want a demo? [y/n/c] "

[[ ${REPLY,,} =~ ^(c|cancel)$ ]] && { echo "Selected Cancel"; exit 1; }

if [[ ${REPLY,,} =~ ^(y|yes|j|ja|s|si|o|oui)$ ]]; then
   echo "Positive"
fi
7
Walter A

Solo tasto singolo

Ecco un approccio più lungo, ma riutilizzabile e modulare:

  • Restituisce 0 = sì e 1 = no
  • Non è necessario premere invio - solo un singolo carattere
  • Può premere enter accettare la scelta predefinita
  • Può disabilitare la scelta predefinita per forzare una selezione
  • Funziona sia per zsh che bash.

Predefinito a "no" quando si preme enter

Si noti che N è in maiuscolo. Qui viene premuto enter, accettando il valore predefinito:

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

Si noti inoltre che [y/N]? è stato automaticamente aggiunto. Il "no" predefinito è accettato, quindi non viene emesso nulla.

Re-Prompt fino a quando viene data una risposta valida:

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

Predefinito a "sì" quando si preme enter

Si noti che Y è in maiuscolo:

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

Sopra, ho appena premuto Invio, quindi il comando è stato eseguito.

Nessun valore predefinito attivo enter - richiede y o n

$ get_yes_keypress "Here you cannot press enter. Do you like this [y/n]? "
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

Qui è stato restituito 1 o false. Nota che con questa funzione di livello inferiore dovrai fornire il tuo prompt [y/n]?.

Codice

# 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=$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 '\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
}
6
Tom Hale

Ho notato che nessuno ha postato una risposta che mostra il menu echo multi-line per un input così semplice da parte dell'utente, quindi ecco il mio consiglio:

#!/bin/bash

function ask_user() {    

echo -e "
#~~~~~~~~~~~~#
| 1.) Yes    |
| 2.) No     |
| 3.) Quit   |
#~~~~~~~~~~~~#\n"

read -e -p "Select 1: " choice

if [ "$choice" == "1" ]; then

    do_something

Elif [ "$choice" == "2" ]; then

    do_something_else

Elif [ "$choice" == "3" ]; then

    clear && exit 0

else

    echo "Please select 1, 2, or 3." && sleep 3
    clear && ask_user

fi
}

ask_user

Questo metodo è stato pubblicato nella speranza che qualcuno possa trovarlo utile e che fa risparmiare tempo.

4
Yokai

Versione a scelta multipla:

ask () {                        # $1=question $2=options
    # set REPLY
    # options: x=..|y=..
    while $(true); do
        printf '%s [%s] ' "$1" "$2"
        stty cbreak
        REPLY=$(dd if=/dev/tty bs=1 count=1 2> /dev/null)
        stty -cbreak
        test "$REPLY" != "$(printf '\n')" && printf '\n'
        (
            IFS='|'
            for o in $2; do
                if [ "$REPLY" = "${o%%=*}" ]; then
                    printf '\n'
                    break
                fi
            done
        ) | grep ^ > /dev/null && return
    done
}

Esempio:

$ ask 'continue?' 'y=yes|n=no|m=maybe'
continue? [y=yes|n=no|m=maybe] g
continue? [y=yes|n=no|m=maybe] k
continue? [y=yes|n=no|m=maybe] y
$

Imposta REPLY su y (all'interno dello script).

4
Ernest A

Ispirato dalle risposte di @Mark e @Myrddin ho creato questa funzione per un prompt universale

uniprompt(){
    while true; do
        echo -e "$1\c"
        read opt
        array=($2)
        case "${array[@]}" in  *"$opt"*) eval "$3=$opt";return 0;; esac
        echo -e "$opt is not a correct value\n"
    done
}

usalo in questo modo:

unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
4
poxtron

Un modo semplice per farlo è con xargs -p o gnu parallel --interactive.

Mi piace il comportamento di xargs un po 'meglio per questo perché esegue ogni comando immediatamente dopo il Prompt come altri comandi unix interattivi, piuttosto che raccogliere gli yesses da eseguire alla fine. (Puoi Ctrl-C dopo aver superato quelli che volevi.)

per esempio.,

echo *.xml | xargs -p -n 1 -J {} mv {} backup/
3
Joshua Goldberg

Vi suggerisco usare la finestra di dialogo ...

Apprendista di Linux: Migliora gli script di Bash Shell usando la finestra di dialogo

Il comando di dialogo consente l'uso di finestre di dialogo negli script di Shell per rendere il loro uso più interattivo.

è semplice e facile da usare, c'è anche una versione gnome chiamata gdialog che prende gli stessi identici parametri, ma mostra lo stile GUI su X.

3
Osama Al-Maadeed

più generico sarebbe:

function menu(){
    title="Question time"
    Prompt="Select:"
    options=("Yes" "No" "Maybe")
    echo "$title"
    PS3="$Prompt"
    select opt in "${options[@]}" "Quit/Cancel"; do
        case "$REPLY" in
            1 ) echo "You picked $opt which is option $REPLY";;
            2 ) echo "You picked $opt which is option $REPLY";;
            3 ) echo "You picked $opt which is option $REPLY";;
            $(( ${#options[@]}+1 )) ) clear; echo "Goodbye!"; exit;;
            *) echo "Invalid option. Try another one.";continue;;
         esac
     done
     return
}
3

Come amico di un comando di una riga ho usato il seguente:

while [ -z $Prompt ]; do read -p "Continue (y/n)?" choice;case "$choice" in y|Y ) Prompt=true; break;; n|N ) exit 0;; esac; done; Prompt=;

Longform scritto, funziona così:

while [ -z $Prompt ];
  do read -p "Continue (y/n)?" choice;
  case "$choice" in
    y|Y ) Prompt=true; break;;
    n|N ) exit 0;;
  esac;
done;
Prompt=;
2
ccDict

Ho usato la dichiarazione case un paio di volte in uno scenario del genere, usare la statino del caso è un buon modo per farlo. Un ciclo while, che ecapsula il blocco case, che utilizza una condizione booleana può essere implementato per mantenere un controllo ancora maggiore del programma e soddisfare molti altri requisiti. Dopo che tutte le condizioni sono state soddisfatte, è possibile utilizzare un break che passerà il controllo alla parte principale del programma. Inoltre, per soddisfare altre condizioni, è possibile aggiungere istruzioni condizionali per accompagnare le strutture di controllo: l'istruzione case e il possibile ciclo while.

Esempio di utilizzo di un'istruzione case per soddisfare la richiesta

#! /bin/sh 

# For potential users of BSD, or other systems who do not
# have a bash binary located in /bin the script will be directed to
# a bourne-Shell, e.g. /bin/sh

# NOTE: It would seem best for handling user entry errors or
# exceptions, to put the decision required by the input 
# of the Prompt in a case statement (case control structure), 

echo Would you like us to perform the option: "(Y|N)"

read inPut

case $inPut in
    # echoing a command encapsulated by 
    # backticks (``) executes the command
    "Y") echo `Do something crazy`
    ;;
    # depending on the scenario, execute the other option
    # or leave as default
    "N") echo `execute another option`
    ;;
esac

exit
2
oOpSgEo
yn() {
  if [[ 'y' == `read -s -n 1 -p "[y/n]: " Y; echo $Y` ]];
  then eval $1;
  else eval $2;
  fi }
yn 'echo yes' 'echo no'
yn 'echo absent no function works too!'
2
jlettvin

In risposta agli altri:

Non è necessario specificare il caso in BASH4, basta usare "," per fare una var in lettere minuscole. Inoltre, non mi piace mettere il codice all'interno del blocco di lettura, ottenere il risultato e gestirlo al di fuori del blocco di lettura IMO. Includere anche una "q" per uscire da IMO. Infine, perché digita "sì", usa solo -n1 e premi y.

Esempio: l'utente può premere y/n e anche q per uscire.

ans=''
while true; do
    read -p "So is MikeQ the greatest or what (y/n/q) ?" -n1 ans
    case ${ans,,} in
        y|n|q) break;;
        *) echo "Answer y for yes / n for no  or q for quit.";;
    esac
done

echo -e "\nAnswer = $ans"

if [[ "${ans,,}" == "q" ]] ; then
        echo "OK Quitting, we will assume that he is"
        exit 0
fi

if [[ "${ans,,}" == "y" ]] ; then
        echo "MikeQ is the greatest!!"
else
        echo "No? MikeQ is not the greatest?"
fi
1
Mike Q

Sì/No/Annulla

Funzione

#!/usr/bin/env bash
@confirm() {
  local message="$*"
  local result=''

  echo -n "> $message (Yes/No/Cancel) " >&2

  while [ -z "$result" ] ; do
    read -s -n 1 choice
    case "$choice" in
      y|Y ) result='Y' ;;
      n|N ) result='N' ;;
      c|C ) result='C' ;;
    esac
  done

  echo $result
}

Uso

case $(@confirm 'Confirm?') in
  Y ) echo "Yes" ;;
  N ) echo "No" ;;
  C ) echo "Cancel" ;;
esac

Conferma con l'input dell'utente pulito

Funzione

#!/usr/bin/env bash
@confirm() {
  local message="$*"
  local result=3

  echo -n "> $message (y/n) " >&2

  while [[ $result -gt 1 ]] ; do
    read -s -n 1 choice
    case "$choice" in
      y|Y ) result=0 ;;
      n|N ) result=1 ;;
    esac
  done

  return $result
}

Uso

if @confirm 'Confirm?' ; then
  echo "Yes"
else
  echo "No"
fi
1
Eduardo Cuomo