bash: non blocking lido dentro de um loop

5

Eu tenho um pequeno script bash

var=a

while true :
do
    echo $var
    sleep 0.5
    read -n 1 -s var
done

Ele apenas imprime o caractere digitado pelo usuário e aguarda a próxima entrada. O que eu quero fazer é, na verdade, não bloquear a leitura, ou seja, a cada 0,5 segundo, imprima o último caractere digitado pelo usuário. Quando o usuário pressiona alguma tecla, ela deve continuar imprimindo a nova tecla infinitamente até a próxima tecla ser pressionada e assim por diante.

Alguma sugestão?

    
por Artak Begnazaryan 11.12.2014 / 16:05

2 respostas

11

De help read :

  -t timeout    time out and return failure if a complete line of input is
        not read within TIMEOUT seconds.  The value of the TMOUT
        variable is the default timeout.  TIMEOUT may be a
        fractional number.  If TIMEOUT is 0, read returns immediately,
        without trying to read any data, returning success only if
        input is available on the specified file descriptor.  The
        exit status is greater than 128 if the timeout is exceeded

Então tente:

while true
do
    echo "$var"
    IFS= read -r -t 0.5 -n 1 -s holder && var="$holder"
done

A variável holder é usada, pois uma variável perde seu conteúdo quando usada com read , a menos que seja somente leitura (caso em que não é útil de qualquer maneira), mesmo se read expirou:

$ declare -r a    
$ read -t 0.5 a
bash: a: readonly variable
code 1

Não consegui encontrar uma maneira de evitar isso.

    
por 11.12.2014 / 16:13
0

Um pouco atrasado, mas a (melhor) solução poderia ser:

while true ; do
    read -r -s -t 0.5; RETVAL=$?
    # ok? echo && continue
    [ $RETVAL -eq 0 ] && echo -E "$REPLY" && continue
    # no timeout ? (EOF or error) break
    [ $RETVAL -gt 128 ] || break
done

IMHO um tempo limite maior não vai machucar ninguém, como "read" retorna assim que uma nova linha estiver disponível ...

    
por 23.08.2016 / 11:45