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.


Tudo isso e muito mais são abordados neste SO Q&A BTW: Qual é o Linux equivalente à pausa do DOS?
— slm


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

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


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

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

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.


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

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!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.