読み取らないとシェルスクリプトループが発生する[閉じる]

読み取らないとシェルスクリプトループが発生する[閉じる]

端末がアクティブなウィンドウでないときに実行中のスクリプトを停止するためにキーボードショートカットを使用する最良の方法を見つけようとしています。

これにより、キーボードイベントを観察する方法のアイデアを得ることができますcat /dev/input/eventX(ここで、Xはキーストロークイベントに対応する数字です)。

evtestその後、イベント(キーストローク)が人間が読める形式で印刷されるまで実行されるツールについて学びました。

これまで私が管理してきたスクリプトですが、期待どおりに動作しません。完璧なソリューションでは、ユーザーはいつでもKey_Spaceを押してスクリプトを停止できますが、ここでは不可能だと思います。だから私の解決策はループの始めに2秒のウィンドウを提供することでした。

#!/bin/bash                                                              
exitCase='*type 1 (EV_KEY), code 57 (KEY_SPACE)*'

while [ true ]  do
    evtest  /dev/input/eventX |  read -s -t 2  line 
    if [ "$line" = "$exitCase" ] 
    then
        echo caught event
        exit 0

    else           
        echo loop doing stuff
    fi
done

問題は、スクリプトが繰り返しなしで一度実行されることです。これを行うより良い方法はありますか?それとも、終了状況に一致する入力が表示されるまでスクリプトを繰り返すようにどのように調整できますか?

もう1つの潜在的な問題は、1つのキーストロークが複数行を印刷することです。したがって、1つが必要な場合がありますevtest /dev/input/eventX | while read line。ただし、試した後は、イベントを待っている間ではなく、イベントでのみ繰り返すことができます。

答え1

パイプの右側はevtest | read line別のサブシェルで実行されるので(したがってline便利な項目を設定しないため)、テストでいいえtrue で、スクリプトは無期限に実行されます。表示されていないスクリプトにコードがある可能性がありますか?

readとにかくから始める必要はありませんevtest。代わりに、以下を使用できますgrep(これにより、最後に述べた「潜在的な問題」も解決されます)。

#!/bin/sh

exitCase='*type 1 (EV_KEY), code 57 (KEY_SPACE)*'

while true; do
    if evtest /dev/input/eventX | grep -q -Fx -e "$exitCase"; then
        echo caught event
        break
    else           
        echo loop doing stuff
    fi
done

evtestまったく同じ行が作成されると、ループは中断されます$exitCase。静かにするように-q指示するオプション(終了状態にのみ興味がある)では、文字列を次のように組み合わせる必要があります。grep-Fgrep$exitCaseひも正規表現ではなく-x行全体を一致させる必要があります(文字列が先頭と末尾に固定されているかのように部分文字列なし)。

grepタイムアウトを適用するには、GNU coreutilsをevtest使用できますtimeout

関連情報