¿Cómo solicito la entrada Sí/No/Cancelar en un script de shell de Linux?


Quiero pausar la entrada en un script de shell y pedirle al usuario que elija. La pregunta estándar de tipo "Sí, No o Cancelar". ¿Cómo puedo lograr esto en un prompt bash típico?

Author: Brandon Rhodes, 2008-10-22

27 answers

El método más simple y más ampliamente disponible para obtener la entrada del usuario en un símbolo del shell es el read comando. La mejor manera de ilustrar su uso es una demostración simple:

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

Otro método, señalado por Steven Huwig, es el de Bash select comando. Aquí está el mismo ejemplo 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 no necesita desinfectar la entrada: muestra las opciones disponibles y escribe un número correspondiente a su elección. También hace bucles automáticamente, por lo que no hay necesidad de un bucle while true para reintentar si dan entrada no válida.

También, por favor echa un vistazo a la excelente respuesta por F. Hauri.

 1306
Author: Myrddin Emrys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-02 06:11:49

Al menos cinco respuestas para una pregunta genérica.

Dependiendo de

Y si quieres

  • pregunta / respuesta simple `en línea " (soluciones genéricas)
  • interfaces bastante formateadas, como ncurses o más gráficas usando libgtk o libqt...
  • utilice la potente capacidad de historial de readline

1. POSIX generic solutions

Podrías usar el comando read, seguido de 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

(Gracias a El comentario de Adam Katz : Reemplazó la prueba anterior con una que es más portátil y evita una bifurcación:)

POSIX, pero característica de clave única

Pero si no quieres que el usuario tenga que pulsar Return , podría escribir:

(Editado: Como @JonathanLeffler acertadamente sugiere, guardar la configuración de stty podría ser mejor que simplemente forzarlos a cuerdo.)

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: Esto fue probado en sh, bash, ksh, dash y busybox!

Lo mismo, pero esperando explícitamente 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

Usando herramientas dedicadas

Hay muchas herramientas que fueron construidos usando libncurses, libgtk, libqt u otras bibliotecas gráficas. Por ejemplo, usando whiptail:

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

Dependiendo de su sistema, es posible que necesite reemplazar whiptail con otra herramienta similar:

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

Donde 20 es la altura del cuadro de diálogo en número de líneas y 60 es la anchura del cuadro de diálogo. Todas estas herramientas tienen casi la misma sintaxis.

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

2. Soluciones específicas de Bash

Básico en línea método{[76]]}
read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
    y|Y )
        echo Yes
    ;;
    * )
        echo No
    ;;
esac

Prefiero usar case así que incluso podría probar para yes | ja | si | oui si es necesario...

en línea con tecla única característica

En bash, podemos especificar la longitud de la entrada prevista para el comando read:

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

Bajo bash, el comando read acepta un parámetro timeout, que podría ser útil.

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

Algunos trucos para herramientas dedicadas

Cuadros de diálogo más sofisticados, más allá de lo simple yes - no propósitos:

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

Barra de progreso:

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
) 

Pequeña demostración:

#!/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

¿Más muestra? Echa un vistazo a Usando whiptail para elegir el dispositivo USB y Selector de almacenamiento extraíble USB: USBKeyChooser

5. Usando la historia de readline

Ejemplo:

#!/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

Esto creará un archivo .myscript.history en su directorio $HOME, del que podría usar los comandos del historial de readline, como Subir, Down , Ctrl+r y otros.

 392
Author: F. Hauri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-29 14:14:00
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
 335
Author: Pistos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-28 20:01:34

Puede usar el comando integrado read; Use la opción -p para preguntar al usuario.

Desde BASH4, ahora puede usar -i para sugerir una respuesta, por lo que el usuario solo tiene que presionar return para ingresarla:

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

(Pero recuerde usar la opción "readline" -e para permitir la edición de líneas con las teclas de flecha)

Si quieres una lógica "sí / no", puedes hacer algo como esto:

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

[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
 129
Author: yPhil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 17:03:00

Bash tiene seleccione para este propósito.

select result in Yes No Cancel
do
    echo $result
done
 98
Author: Steven Huwig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-22 18:14:01
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
 53
Author: serg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-03 13:23:04

Aquí hay algo que he reunido:

#!/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

Soy un principiante, así que toma esto con un grano de sal, pero parece funcionar.

 30
Author: mpen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-30 17:59:18
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?"

...
 24
Author: SumoRunner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-28 15:01:15

Quieres:

  • Bash builtin comandos (es decir, portable)
  • Compruebe TTY
  • Respuesta predeterminada
  • Tiempo de espera
  • Pregunta de color

Fragmento

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

Explicaciones

  • [[ -t 0 ]] && read ... = > Call command read if TTY
  • read -n 1 = > Espere un carácter
  • $'\e[1;32m ... \e[0m ' = > Imprimir en verde
    (verde está bien porque legible en ambos fondos blanco / negro)
  • [[ $do_xxxx =~ ^(y|Y|)$ ]] = > regex bash

Tiempo de espera = > La respuesta predeterminada es 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
 23
Author: olibre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 10:36:50

La forma más fácil de lograr esto con el menor número de líneas es la siguiente:

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

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

El if es solo un ejemplo: depende de usted cómo manejar esta variable.

 20
Author: Apurv Nerlekar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-14 16:06:39

Utilice el 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

Y luego todas las otras cosas que necesitas

 17
Author: ThatLinuxGuy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-14 16:07:42

Esta solución lee un solo carácter y llama a una función en una respuesta sí.

read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    do_something      
fi
 16
Author: Dennis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-15 07:04:18
read -e -p "Enter your choice: " choice

La opción -e permite al usuario editar la entrada usando las teclas de flecha.

Si desea utilizar una sugerencia como entrada:

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

-i la opción imprime una entrada sugerente.

 12
Author: Jahid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-19 00:37:02

Lo siento por publicar en una publicación tan antigua. Hace algunas semanas me enfrentaba a un problema similar, en mi caso necesitaba una solución que también funcionara dentro de un instalador-script en línea, por ejemplo: curl -Ss https://raw.github.com/_____/installer.sh | bash

Usar read yesno < /dev/tty funciona bien para mí:

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

Espero que esto ayude a alguien.

 9
Author: xyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-22 11:07:15

Para obtener un buen ncurses-como inputbox utilice el comando diálogo así:

#!/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

El paquete de diálogo se instala de forma predeterminada al menos con SUSE Linux.

 7
Author: Thorsten Staerk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-06 11:40:47

Versión de opción múltiple:

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
}

Ejemplo:

$ 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
$

Establecerá REPLY a y (dentro del script).

 4
Author: Ernest A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-28 17:50:02

Inspirado por las respuestas de @Mark y @ Myrddin, creé esta función para un mensaje universal

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
}

Úsalo así:

unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
 4
Author: poxtron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-08 00:40:48

Le sugiero que use dialog...

Linux Apprentice: Mejora los Scripts de Shell Bash Usando Dialog

El comando dialog habilita el uso de cajas de ventana en scripts de shell para hacer su uso más interactivo.

Es simple y fácil de usar, también hay una versión de gnome llamada gdialog que toma exactamente los mismos parámetros, pero muestra el estilo GUI en X.

 3
Author: Osama Al-Maadeed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-09 23:19:57

Una forma sencilla de hacerlo es con xargs -p o gnu parallel --interactive.

Me gusta el comportamiento de xargs un poco mejor para esto porque ejecuta cada comando inmediatamente después del prompt como otros comandos interactivos de unix, en lugar de recopilar los yes para ejecutar al final. (Puede Ctrl-C después de pasar por los que quería.)

Por ejemplo,

echo *.xml | xargs -p -n 1 -J {} mv {} backup/
 3
Author: Joshua Goldberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-08 19:30:25

Más genérico sería:

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
Author: Alexander Löfqvist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-29 11:39:09

Solo pulsación de tecla

Aquí hay un enfoque más largo, pero reutilizable y modular:

  • Devuelve 0 = sí y 1=no
  • No se requiere presionar enter-solo un solo carácter
  • Puede presionar enter para aceptar la opción predeterminada
  • Puede desactivar la opción predeterminada para forzar una selección
  • Funciona tanto para zsh como para bash.

Por defecto a" no " al presionar enter

Tenga en cuenta que el N está en mayúscula. Aqui se presiona enter, aceptando el valor predeterminado:

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

También tenga en cuenta que [y/N]? se añadió automáticamente. Se acepta el " no " predeterminado, por lo que no se hace eco de nada.

Vuelva a preguntar hasta que se dé una respuesta válida:

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

Por defecto a" sí " al presionar enter

Tenga en cuenta que el Y está en mayúscula:

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

Arriba, simplemente presioné enter, por lo que el comando se ejecutó.

No hay defecto en enter - require 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

Aquí, 1 o false fue devuelto. Tenga en cuenta que con esta función de nivel inferior tendrá que proporcionar su propio mensaje [y/n]?.

Código

# 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
}
 3
Author: Tom Hale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-01 07:25:13
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
Author: jlettvin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-24 03:38:54

Como amigo de un comando de una línea usé lo siguiente:

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=;

Escrito de forma larga, funciona así:

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
Author: ccDict,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-05 06:37:02

He usado la instrucción case un par de veces en tal escenario, usar la declaración case es una buena manera de hacerlo. Un bucle while, que ecapsula el bloque case, que utiliza una condición booleana puede ser implementado con el fin de mantener aún más control del programa, y cumplir con muchos otros requisitos. Después de que se hayan cumplido todas las condiciones, se puede usar un break que pasará el control de nuevo a la parte principal del programa. Además, para cumplir otras condiciones, por supuesto condicional se pueden añadir sentencias para acompañar a las estructuras de control: sentencia case y posible bucle while.

Ejemplo de uso de una declaración case para cumplir con su solicitud

#! /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
Author: oOpSgEo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-08 09:43:18

Me di cuenta de que nadie publicó una respuesta que muestra el menú de eco multilínea para la entrada de usuario tan simple, así que aquí está mi ir en él:

#!/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

Este método fue publicado con la esperanza de que alguien pueda encontrarlo útil y ahorrador de tiempo.

 2
Author: Yokai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-08 07:42:38

Sí / No / Cancelar

Función

#!/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

Confirme con la entrada limpia del usuario

Función

#!/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
 0
Author: Eduardo Cuomo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-15 18:53:22

En respuesta a otros:

No necesita especificar mayúsculas y minúsculas en BASH4, solo use',, ' para hacer un var en minúsculas. También me disgusta mucho poner código dentro del bloque de lectura, obtener el resultado y tratar con él fuera de la OMI bloque de lectura. También incluye una ' q ' para salir de IMO. Por último, ¿por qué escribir ' sí ' solo use-n1 y tenga la prensa y.

Ejemplo: el usuario puede presionar y / n y también q para salir.

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
 0
Author: Mike Q,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-20 03:09:41