bash:ループ内で非遮断を読み取る

bash:ループ内で非遮断を読み取る

以下に小さなbashスクリプトがあります

var=a

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

ユーザーが入力した文字を印刷し、次の入力を待ちます。私が望むのは、実際に読み取りをブロックしないことです。つまり、0.5秒ごとにユーザーが入力した最後の文字を印刷します。ユーザーがキーを押すと、次のキーを押すまで新しいキーを印刷する必要があります。

どんな提案がありますか?

答え1

から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

だから試してみてください:

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

これは、変数が読み取り専用でない限り(何ら役に立たない場合)、タイムアウトしてもholder変数と一緒に使用するとその内容が失われるために使用されます。readread

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

私はこれを防ぐ方法を見つけることができません。

答え2

少し遅れましたが(より良い)解決策は次のとおりです。

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、より大きなタイムアウトは誰にも害を与えません。新しい行が利用可能になるとすぐに「読み込み」が返されるからです。

関連情報