Quiero pausar la entrada en un script de shell y pedirle al usuario que elija.
La norma Yes
, No
o Cancel
tipo de pregunta.
¿Cómo logro esto en un típico bash prompt?
read
comando para solicitar
Quiero pausar la entrada en un script de shell y pedirle al usuario que elija.
La norma Yes
, No
o Cancel
tipo de pregunta.
¿Cómo logro esto en un típico bash prompt?
read
comando para solicitar
Respuestas:
El método más simple y más ampliamente disponible para obtener la entrada del usuario en un indicador de comandos de 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 select
comando de Bash . 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
usted no necesita desinfectar la entrada: muestra las opciones disponibles y escribe un número correspondiente a su elección. También realiza un bucle automático, por lo que no es necesario que un while true
bucle vuelva a intentarlo si proporcionan una entrada no válida.
Además, Léa Gris demostró una forma de hacer que el lenguaje de solicitud fuera agnóstico en su respuesta . La adaptación de mi primer ejemplo para servir mejor a varios idiomas podría verse así:
set -- $(locale LC_MESSAGES)
yesptrn="$1"; noptrn="$2"; yesword="$3"; noword="$4"
while true; do
read -p "Install (${yesword} / ${noword})? " yn
case $yn in
${yesptrn##^} ) make install; break;;
${noptrn##^} ) exit;;
* ) echo "Answer ${yesword} / ${noword}.";;
esac
done
Obviamente, otras cadenas de comunicación permanecen sin traducir aquí (Instalar, Responder), lo que debería abordarse en una traducción más completa, pero incluso una traducción parcial sería útil en muchos casos.
Finalmente, mira la excelente respuesta de F. Hauri .
exit
a break
para evitar cerrar la pestaña cuando seleccioné 'no'.
break
en el select
si no hay bucle?
Dependiendo de
y si tu quieres
Puede usar el read
comando, 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 al comentario de Adam Katz : reemplazó la prueba anterior con una que es más portátil y evita una bifurcación :)
Pero si no desea que el usuario tenga que golpear Return, puede escribir:
( Editado: como @JonathanLeffler sugiere correctamente, guardar la configuración de stty podría ser mejor que simplemente obligarlos a estar cuerdos ).
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 bajosh, golpetazo, ksh, guión y busybox!
Lo mismo, pero esperando explícitamente yo 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
Hay muchas herramientas que fueron construidos usando libncurses
, libgtk
, libqt
u otras librerías 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 deba reemplazarlo 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 el 60
ancho 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 ...
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
para poder probar yes | ja | si | oui
si es necesario ...
En bash, podemos especificar la longitud de la entrada prevista para el read
comando:
read -n 1 -p "Is this a good question (y/n)? " answer
En bash, el read
comando acepta un parámetro de tiempo de espera , 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
Cuadros de diálogo más sofisticados, más allá de yes - no
propósitos simples :
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 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
Más muestra? Eche un vistazo al uso de Whiptail para elegir un dispositivo USB y un selector de almacenamiento extraíble USB: USBKeyChooser
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 $HOME
directorio, lo que se podría utilizar comandos de la historia de readline, como Up, Down, Ctrl+ rotros y.
stty
ofrece la -g
opción de uso: old_stty=$(stty -g); stty raw -echo; …; stty "$old_stty"
. Esto restaura la configuración exactamente como se encontraron, lo que puede o no ser lo mismo stty -sane
.
case
POSIX así como bash (use una condición comodín en lugar de una subcadena bash:) case $answer in; [Yy]* ) echo Yes ;;
, pero prefiero usar una declaración condicional en su lugar, favoreciendo [ "$answer" != "${answer#[Yy]}" ]
su echo "$answer" | grep -iq ^y
. Es más portátil (algunos greps que no son GNU no se implementan -q
correctamente) y no tiene la llamada al sistema. ${answer#[Yy]}
usa la expansión de parámetros para eliminar Y
o y
desde el principio $answer
, causando una desigualdad cuando cualquiera de los dos está presente. Esto funciona en cualquier shell POSIX (guión, ksh, bash, zsh, busybox, etc.).
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
Puede usar el comando de lectura incorporado ; Use la -p
opción para preguntar al usuario con una pregunta.
Desde BASH4, ahora puede usar -i
para sugerir una respuesta:
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ínea con las teclas de flecha)
Si desea una lógica de "sí / no", puede hacer algo como esto:
read -e -p "
List the content of your home dir ? [Y/n] " YN
[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
FILEPATH
es el nombre de la variable que ha elegido y se configura con la respuesta al símbolo del sistema. Entonces, si tuviera que ejecutar vlc "$FILEPATH"
, por ejemplo, vlc
abriría ese archivo.
-e
segundo ejemplo (simple sí / no)?
-e -p
lugar de -ep
?
-e
indicador / opción, es posible que (según la implementación) no pueda escribir "y", y luego cambiar de opinión y reemplazarlo con una "n" (o cualquier otra cosa); Al documentar un comando, enumerar las opciones por separado es mejor para facilitar la lectura / claridad, entre otras razones.
Bash ha seleccionado para este propósito.
select result in Yes No Cancel
do
echo $result
done
exit
interior :)
Ctrl-D
Pero, por supuesto, el código real que lo use necesitará un descanso o una salida en el cuerpo).
exit
saldrá de la escritura de todos juntos, break
sólo salir del bucle que se encuentra (si se encuentra en una while
o case
bucle)
Aquí hay algo que puse juntos:
#!/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 tómalo con un grano de sal, pero parece funcionar.
case $yn in
a case ${yn:-$2} in
, puede usar el segundo argumento como valor predeterminado, Y o N.
case $yn
a case "${yn:-Y}"
tener sí como predeterminado
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?"
...
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
[[ -t 0 ]] && read ...
=> Llamar comando read
si TTYread -n 1
=> Espera un personaje$'\e[1;32m ... \e[0m '
=> Imprimir en verde [[ $do_xxxx =~ ^(y|Y|)$ ]]
=> bash regexdo_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
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.
Usa el read
comando:
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
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
echo
para verlo por ti mismo.
Para obtener un bonito cuadro de entrada similar a ncurses, use el cuadro de diálogo de comando como este:
#!/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 por defecto al menos con SUSE Linux. Parece:
read -e -p "Enter your choice: " choice
La -e
opción 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.
-e
-i
sí , no trabajes en sh (Bourne shell), pero la pregunta está etiquetada específicamente como bash ..
Puede usar el valor predeterminado REPLY
en a read
, convertir a minúsculas y comparar con un conjunto de variables con una expresión.
El script también es compatible con 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
Es posible manejar una "opción Sí / No" local en un shell POSIX; Al utilizar las entradas de la LC_MESSAGES
categoría de configuración regional, witch proporciona patrones RegEx listos para que coincidan con una entrada y cadenas para Sí No.
#!/usr/bin/env sh
# Getting LC_MESSAGES values into variables
# shellcheck disable=SC2046 # Intended IFS splitting
IFS='
' set -- $(locale LC_MESSAGES)
yesexpr="$1"
noexpr="$2"
yesstr="$3"
nostr="$4"
messages_codeset="$5" # unused here, but kept as documentation
# Display Yes / No ? prompt into locale
echo "$yesstr / $nostr ?"
# Read answer
read -r yn
# Test answer
case "$yn" in
# match only work with the character class from the expression
${yesexpr##^}) echo "answer $yesstr" ;;
${noexpr##^}) echo "answer $nostr" ;;
esac
EDITAR: Como @Urhixidur mencionó en su comentario :
Desafortunadamente, POSIX solo especifica los dos primeros (yesexpr y noexpr). En Ubuntu 16, yesstr y nostr están vacíos.
Ver: https://www.ee.ryerson.ca/~courses/ele709/susv4/xrat/V4_xbd_chap07.html#tag_21_07_03_06
LC_MESSAGES
Las palabras clave
yesstr
ynostr
locale y los elementosYESSTR
yNOSTR
langinfo se usaban anteriormente para hacer coincidir las respuestas afirmativas y negativas del usuario. En POSIX.1-2008, layesexpr
,noexpr
,YESEXPR
, yNOEXPR
expresiones regulares extendidas su sustitución. Las aplicaciones deben usar las funciones de mensajería basadas en la localización general para emitir mensajes de solicitud que incluyen ejemplos de respuestas deseadas.
Alternativamente, usando configuraciones locales como Bash:
#!/usr/bin/env bash
IFS=$'\n' read -r -d '' yesexpr noexpr _ < <(locale LC_MESSAGES)
printf -v yes_or_no_regex "(%s)|(%s)" "$yesexpr" "$noexpr"
printf -v prompt $"Please answer Yes (%s) or No (%s): " "$yesexpr" "$noexpr"
declare -- answer=;
until [[ "$answer" =~ $yes_or_no_regex ]]; do
read -rp "$prompt" answer
done
if [[ -n "${BASH_REMATCH[1]}" ]]; then
echo $"You answered: Yes"
else
echo $"No, was your answer."
fi
La respuesta coincide con las expresiones regulares proporcionadas por el entorno local.
Para traducir los mensajes restantes, utilice bash --dump-po-strings scriptname
para generar las cadenas de po para la localización:
#: scriptname:8
msgid "Please answer Yes (%s) or No (%s): "
msgstr ""
#: scriptname:17
msgid "You answered: Yes"
msgstr ""
#: scriptname:19
msgid "No, was your answer."
msgstr ""
yesexpr
y noexpr
en un entorno de shell es usarlo en la correspondencia RegEx específica de Bashif [[ "$yn" =~ $yesexpr ]]; then echo $"Answered yes"; else echo $"Answered no"; fi
Aquí hay un enfoque más largo, pero reutilizable y modular:
0
= sí y 1
= nozsh
y bash
.Tenga en cuenta que el N
está en mayúscula. Aquí se presiona enter, aceptando el valor predeterminado:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?
También tenga en cuenta que eso [y/N]?
se agregó automáticamente. Se acepta el "no" predeterminado, por lo que no se repite 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 *
Tenga en cuenta que el Y
está en mayúscula:
$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *
Arriba, solo presioné enter, por lo que el comando se ejecutó.
y
on
$ 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 falso fue devuelto. Tenga en cuenta que con esta función de nivel inferior deberá proporcionar su propia[y/n]?
aviso.
# 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
}
Show dangerous command [y/N]? [y/n]?
yShow dangerous command [Y/n]? [y/n]?
Perdón 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 script de instalación 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.
tty
entrada como lo hiciste también lo habría hecho bien para ti, y también haber hecho un bucle en una entrada incorrecta (imagina algunos caracteres en el búfer; tu método obligaría al usuario a elegir siempre no).
Me di cuenta de que nadie publicó una respuesta que mostrara el menú de eco de varias líneas para una entrada de usuario tan simple, así que aquí está mi intento:
#!/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 que ahorre tiempo.
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
$
Se establecerá REPLY
en y
(dentro del script).
Te sugiero que uses el diálogo ...
Aprendiz de Linux: Mejore los scripts de Bash Shell usando el diálogo
El comando de diálogo permite el uso de cuadros de ventana en scripts de shell para que su uso sea 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 su estilo GUI en X.
Inspirado por las respuestas de @Mark y @Myrddin, creé esta función para un aviso 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"
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
}
Una manera simple de hacer esto es con xargs -p
o gnuparallel --interactive
.
Me gusta el comportamiento de xargs un poco mejor para esto porque ejecuta cada comando inmediatamente después de la solicitud como otros comandos interactivos de Unix, en lugar de recopilar los yesses para ejecutarlos al final. (Puede hacer Ctrl-C después de pasar por los que desea).
p.ej,
echo *.xml | xargs -p -n 1 -J {} mv {} backup/
xargs --interactive
se limita a sí o no. Mientras eso sea todo lo que necesita, puede ser suficiente, pero mi pregunta original dio un ejemplo con tres resultados posibles. Sin embargo, me gusta mucho que sea transmisible; Muchos escenarios comunes se beneficiarían de su capacidad de canalización.
Como amigo de un comando de una línea, utilicé 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=;
Forma larga escrita, 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=;
He usado la case
declaración un par de veces en tal escenario, usar el enunciado del caso es una buena manera de hacerlo. Se puede implementar un while
bucle, que encapsula el case
bloque, que utiliza una condición booleana para mantener aún más control del programa y cumplir con muchos otros requisitos. Una vez que se hayan cumplido todas las condiciones, break
se puede utilizar un que devolverá el control a la parte principal del programa. Además, para cumplir otras condiciones, por supuesto, se pueden agregar declaraciones condicionales para acompañar las estructuras de control: case
declaración y posible while
bucle.
Ejemplo de uso de una case
declaración 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
#!/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
}
case $(@confirm 'Confirm?') in
Y ) echo "Yes" ;;
N ) echo "No" ;;
C ) echo "Cancel" ;;
esac
#!/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
}
if @confirm 'Confirm?' ; then
echo "Yes"
else
echo "No"
fi
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!'
yn(){ read -s -n 1 -p '[y/n]'; test "$REPLY" = "y" ; } yn && echo success || echo failure
En respuesta a otros:
No necesita especificar mayúsculas y minúsculas en BASH4, solo use '' para hacer una var en minúsculas. También me desagrada poner código dentro del bloque de lectura, obtener el resultado y tratarlo fuera del bloque de lectura IMO. También incluya una 'q' para salir de la OMI. Por último, ¿por qué escribir 'sí'? Solo use -n1 y presione y.
Ejemplo: el usuario puede presionar y / ny 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
La mayoría de las veces en tales escenarios, debe continuar ejecutando el script hasta que el usuario continúe ingresando "sí" y solo necesite detenerse cuando el usuario ingrese "no". ¡El siguiente fragmento lo ayudaría a lograr esto!
#!/bin/bash
input="yes"
while [ "$input" == "yes" ]
do
echo "execute script functionality here..!!"
echo "Do you want to continue (yes/no)?"
read input
done
[yn]
opción, la que está en mayúscula es la predeterminada, es decir, el valor predeterminado es[Yn]
"sí" y el valor[yN]
predeterminado es "no". Ver ux.stackexchange.com/a/40445/43532