presione espacio para continuar

74

¿Cómo detengo un script bash hasta que un usuario ha presionado Space?

Me gustaría tener la pregunta en mi guión

Presione la barra espaciadora para continuar o CTRL+ Cpara salir

y luego el script debe detenerse y esperar hasta que se presione Space.

rubo77
fuente

Respuestas:

58

Puedes usar read:

read -n1 -r -p "Press space to continue..." key

if [ "$key" = '' ]; then
    # Space pressed, do something
    # echo [$key] is empty when SPACE is pressed # uncomment to trace
else
    # Anything else pressed, do whatever else.
    # echo [$key] not empty
fi
AleksanderKseniya
fuente
12
Debe agregar -s para no imprimir el carácter presionado en el terminal. Y agregue un salto de línea al final, o la salida continuará directamente en la misma línea que la pregunta. Lo mejor sería:read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
rubo77
1
Este script no funciona. Solo lo probé en Red Hat Linux ... El elsebloque siempre se ejecuta, incluso cuando se presiona la barra espaciadora.
Robert
3
@robert Es porque no lo usas bash. Funciona si lo usas read _, si tienes otro shell que no sea bash.
Niklas Rosencrantz
¿Debería ''contener un espacio dentro?
Jose Antonio Dura Olmos
Esto es ''para una cadena vacía. No hay espacio adentro. Supongo que también encaja si ingresas ENTER o TAB
rubo77
45

El método discutido en estas preguntas y respuestas sobre SO es probablemente el mejor candidato para una alternativa al pausecomportamiento al que está acostumbrado en Windows cuando hace archivos BAT.

$ read -rsp $'Press any key to continue...\n' -n1 key

Ejemplo

Aquí estoy ejecutando lo anterior y luego simplemente presiono cualquier tecla, en este caso la Dtecla.

$ read -rsp $'Press any key to continue...\n' -n1 key
Press any key to continue...
$ 

Referencias

slm
fuente
Quiero decir, ¿por qué $antes de la cadena aquí -rsp $'Press:?
rubo77
2
@ rubo77 - ah. Así es como puedes hacer una cadena literal con caracteres especiales. Tiene la forma: $ '...'
slm
1
@ rubo77: eso es diferente. Es un signo de dólar con comillas dobles, utilicé un dólar con comillas simples. Elimina ese comentario, está mal.
slm
1
Ah, ya entiendo. En caso de que coloque secuencias escapadas dentro de la cadena de solicitud. ver wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
rubo77
@ rubo77: sí, esa notación permite incluir secuencias de escape sin echo -e "..."líneas adicionales . Es mucho más compacto en esas situaciones.
slm
6
hold=' '
printf "Press 'SPACE' to continue or 'CTRL+C' to exit : "
tty_state=$(stty -g)
stty -icanon
until [ -z "${hold#$in}" ] ; do
    in=$(dd bs=1 count=1 </dev/tty 2>/dev/null)
done
stty "$tty_state"

Esto ahora imprime un mensaje sin una nueva línea final, se maneja de CTRL+Cmanera confiable, invoca sttysolo con la frecuencia necesaria y restaura el tty de control exactamente al estado en el que se sttyencontró. Busque man sttyinformación sobre cómo controlar explícitamente los ecos, los caracteres de control y todo.

También puedes hacer esto:

printf "Press any key to continue or 'CTRL+C' to exit : "
(tty_state=$(stty -g)
stty -icanon
LC_ALL=C dd bs=1 count=1 >/dev/null 2>&1
stty "$tty_state"
) </dev/tty

Podrías hacerlo ENTER, sin [pruebas ]y sin sttygusto:

sed -n q </dev/tty
mikeserv
fuente
5

Podrías crear una función para ello:

pause(){
 read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
}

Entonces puedes usar esto en todas partes en tu script:

pause
rubo77
fuente
si eres nuevo en el scripting de shell, debes poner la función en la parte superior de tu script antes de usarlo
Richard
3

un forro perezoso:

echo "Press any key to continue or Ctrl+C to cancel"
read && do_something.sh

la desventaja es que pierde el control cuando el usuario presiona ctrl + c. El script siempre saldrá con el código 130 en ese caso.

gcb
fuente
2

La configuración IFSpara vaciar la cadena suprime el comportamiento predeterminado de lectura de recortar espacios en blanco.

try_this() {
  echo -n "Press SPACE to continue or Ctrl+C to exit ... "
  while true; do
    # Set IFS to empty string so that read doesn't trim
    # See http://mywiki.wooledge.org/BashFAQ/001#Trimming
    IFS= read -n1 -r key
    [[ $key == ' ' ]] && break
  done
  echo
  echo "Continuing ..."
}
try_this

ACTUALIZACIÓN 2018-05-23: Podemos simplificar esto usando la variable REPLY, que no está sujeta a división de palabras:

try_this() {
  echo -n "Press SPACE to continue or Ctrl+C to exit ... "
  while true; do
    read -n1 -r
    [[ $REPLY == ' ' ]] && break
  done
  echo
  echo "Continuing ..."
}
try_this
Robin A. Meade
fuente
1

Aquí hay una manera que funciona en ambos bashy zsh, y asegura E / S al terminal:

# Prompt for a keypress to continue. Customise prompt with $*
function pause {
  >/dev/tty printf '%s' "${*:-Press any key to continue... }"
  [[ $ZSH_VERSION ]] && read -krs  # Use -u0 to read from STDIN
  [[ $BASH_VERSION ]] && </dev/tty read -rsn1
  printf '\n'
}
export_function pause

¡Ponlo en tu .{ba,z}shrcpara Gran Justicia!

Tom Hale
fuente