Premi lo spazio per continuare


74

Come posso interrompere uno script bash fino a quando un utente non ha premuto Space?

Vorrei avere la domanda nella mia sceneggiatura

Premi lo spazio per continuare o CTRL+ Cper uscire

e quindi lo script dovrebbe fermarsi e attendere fino a quando non viene premuto Space.


Tutto questo e molto altro è affrontato in questo SO Q&A BTW: qual è l'equivalente di Linux alla pausa DOS?
slm


Risposte:


58

Puoi usare 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

12
Dovresti aggiungere -s per non stampare il carattere premuto sul terminale. E aggiungi un'interruzione di riga alla fine, altrimenti l'output continuerà direttamente nella stessa riga come la domanda. Il migliore sarebbe:read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
rubo77,

1
Questo script non funziona. L'ho appena testato su Red Hat Linux ... Il elseblocco funziona sempre, anche quando viene premuta la barra spaziatrice.
Robert,

3
@robert È perché non usi bash. Funziona se usi read _invece, se hai qualche altra shell di bash.
Niklas Rosencrantz,

Dovrebbe ''contenere uno spazio dentro?
Jose Antonio Dura Olmos,

Questo è ''per una stringa vuota. Nessuno spazio dentro. Immagino che
vada

45

Il metodo discusso in queste domande e risposte è probabilmente il miglior candidato per un'alternativa al pausecomportamento a cui sei abituato su Windows quando esegui file BAT.

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

Esempio

Qui sto eseguendo quanto sopra e quindi semplicemente premendo qualsiasi tasto, in questo caso il Dtasto.

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

Riferimenti


Voglio dire perché il $prima della stringa qui -rsp $'Press:?
rubo77,

2
@ rubo77 - ah. È così che puoi fare una stringa letterale con caratteri speciali. È nella forma: $ '...'
slm

1
@ rubo77 - è diverso. Questo è un segno di dollaro con virgolette doppie, ho usato un dollaro con virgolette singole. Si prega di eliminare quel commento, è sbagliato.
slm

1
Ah capisco. Nel caso in cui si inseriscano sequenze di escape all'interno della stringa di prompt. vedi wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
rubo77

@ rubo77: sì, la notazione consente di includere sequenze di escape senza echo -e "..."righe aggiuntive . È molto più compatto in quelle situazioni.
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"

Questo ora stampa un prompt senza una nuova riga finale, gestisce in CTRL+Cmodo affidabile, invoca sttysolo tutte le volte che è necessario e ripristina il tty di controllo esattamente allo stato in cui lo ha sttytrovato. Cerca man sttyinformazioni su come controllare esplicitamente gli echi, controllare i caratteri e tutto il resto.

Potresti anche fare questo:

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

Potresti farlo con ENTER, nessun [test ]e nessun sttylike:

sed -n q </dev/tty

5

È possibile creare una funzione per esso:

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

Quindi puoi usarlo ovunque nel tuo script:

pause

se non conosci la shell scripting - devi mettere la funzione in cima allo script prima di usarla
Richard

3

lazy one liner:

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

lo svantaggio è che perdi il controllo quando l'utente preme ctrl + c. In questo caso lo script uscirà sempre con il codice 130.


2

Le impostazioni IFSper svuotare la stringa eliminano il comportamento predefinito di lettura del taglio degli spazi bianchi.

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

AGGIORNAMENTO 2018-05-23: Possiamo semplificarlo utilizzando la variabile REPLY, che non è soggetta alla suddivisione in parole:

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

1

Ecco un modo che funziona in entrambi bashe zsh, e garantisce l'I / O al terminale:

# 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

Mettilo nel tuo .{ba,z}shrcper la Grande Giustizia!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.