Pressione espaço para continuar

73

Como interrompo um script bash até que um usuário tenha pressionado Space?

Eu gostaria de ter a pergunta no meu script

Pressione espaço para continuar ou CTRL+ Cpara sair

e o script deve parar e aguardar até que o espaço seja pressionado.

rubo77
fonte
Tudo isso e muito mais são abordados neste SO Q&A BTW: Qual é o Linux equivalente à pausa do DOS?
slm
relacionado: unix.stackexchange.com/questions/293940/…
Trevor Boyd Smith

Respostas:

58

Você pode 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
fonte
12
Você deve adicionar -s para não imprimir o caractere pressionado no terminal. E adicione uma quebra de linha no final, ou a saída continuará diretamente na mesma linha que a pergunta. O melhor seria:read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
rubo77
11
Este script não funciona. Apenas testei no Red Hat Linux ... O elsebloco sempre roda, mesmo quando a barra de espaço é pressionada.
robert
3
@robert É porque você não usa bash. Funciona se você usar em read _vez disso, se tiver algum outro shell que não bash.
Niklas Rosencrantz
Deve ''conter um espaço dentro?
Jose Antonio Dura Olmos
Isto é ''para uma string vazia. Não há espaço dentro. Eu acho que, ele também se encaixa, se você digitar ENTER ou TAB
rubo77
44

O método discutido nas perguntas e respostas SO é provavelmente o melhor candidato para uma alternativa ao pausecomportamento que você está acostumado no Windows ao executar arquivos BAT.

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

Exemplo

Aqui, estou executando o procedimento acima e simplesmente pressionando qualquer tecla, neste caso a Dtecla.

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

Referências

slm
fonte
Quero dizer, por que o $antes da string aqui -rsp $'Press:?
rubo77
2
@ rubo77 - ah. É assim que você pode criar uma string literal com caracteres especiais. É da forma: $ '...'
slm
11
@ Rubo77 - isso é diferente. É um cifrão com aspas duplas, usei um dólar com aspas simples. Por favor, exclua esse comentário, está errado.
slm
11
Ah, eu entendi. Caso você coloque sequências de escape dentro da string de prompt. veja wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
rubo77
@ rubo77 - sim, que a notação permite que sequências de escape sejam incluídas sem nenhuma echo -e "..."linha extra . É muito mais compacto nessas situações.
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"

Agora, ele imprime um prompt sem uma nova linha à direita, lida com CTRL+Csegurança, chama sttyapenas quantas vezes for necessário e restaura o controle tty exatamente ao estado em que o sttyencontrou. Procure man sttyinformações sobre como controlar explicitamente ecos, controlar caracteres e tudo.

Você também pode fazer isso:

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

Você poderia fazê-lo com ENTER, sem [testes ]e não sttycomo:

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

Você pode criar uma função para isso:

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

Então você pode usar isso em qualquer lugar do seu script:

pause
rubo77
fonte
se você é novo no shell script - você precisa colocar a função na parte superior do seu script antes de usá-lo #
21216 Richard Richard
3

um forro preguiçoso:

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

a desvantagem é que você perde o controle quando o usuário pressiona ctrl + c. O script sempre sairá com o código 130 nesse caso.

gcb
fonte
2

As configurações IFSpara string vazia suprimem o comportamento padrão da leitura de aparar o espaço em branco.

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

UPDATE 2018-05-23: Podemos simplificar isso usando a variável REPLY, que não está sujeita à divisão de palavras:

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
fonte
1

Aqui está uma maneira que funciona em ambos bashe zsh, e garante I / O para o 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

Coloque-o no seu .{ba,z}shrcpara Grande Justiça!

Tom Hale
fonte