スペースバーで Bash スクリプトを停止するにはどうすればいいですか?

スペースバーで Bash スクリプトを停止するにはどうすればいいですか?

私は Bash で書かれたルービック キューブのストップウォッチに取り組んでいますが、できるだけ早く終了する必要がある場合はCtrl+ は実行できないため、スペース バーを押して停止したいと考えています。C

では、スペースバーだけでプログラムを停止する方法はありますか?

kill私は理解できなかったコマンドを見上げました。

コードのストップウォッチ部分は次のとおりです。

TMP0=$(date +%s%N)
while true; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf "\r$(($DTMP/1000000000)).${DTMP:(-9):2}"
done

答え1

Ctrl+を押すと、フォアグラウンド プロセス グループに SIGINT を送信するのはターミナルですc。任意の文字でこれを実行するように設定できますが、スクリプトの終了時に古い設定を復元する必要があります。

#!/bin/bash

settings="$(stty -g)"
trap 'stty "$settings"' EXIT
stty intr ' '

TMP0=$(date +%s%N)
while true; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf '\r%s' "$(($DTMP/1000000000)).${DTMP:(-9):2}"
done

settings="$(stty -g)"古い設定を保存します。stty intr ' 'ターミナルが+Spaceの代わりに に反応するようにします。スクリプトの終了時に古い設定を復元する役割を担います。Ctrlctrap 'stty "$settings"' EXIT

ノート:

  • トラップのコードでは、stty $settingsは よりも優れていますstty "$settings"。これは「常に引用する"ルール。引用符で囲むと単語の分割やファイル名の生成(グロブ)が防止されますが、の実装によってはstty単語の分割が必要な場合があり、その場合は変数を引用符で囲んではなりません。ファイル名生成による有害な副作用を回避するために、仕様stty -gこの機能をトリガーしない文字列を生成する必要があります。

    編集:それはPOSIX仕様の欠陥でした上記のコードは修正されました。

  • 何か問題が発生し、SIGINT がまだ生成される対話型シェルになっている場合はSpace、手動で呼び出す必要があります。コマンドにはスペースがありますが、 +stty intr ^Cを押すことでリテラルのスペース文字を入力できることに留意してください。Ctrlv Space

  • 静的形式と動的データの方が、使用した動的形式よりも のprintf '\r%s' …「哲学」に適合すると思われるため、使用しました。printf

「+ 」Spaceの代わりに「 +」は、が特別になると、 +は特別ではなくなります。これは欠陥と言えるかもしれません。CtrlcSpaceCtrlcCtrlユーザーは+cが特別なものであり続けることを期待する両方を同時に特別にするのは簡単ではありませんが、ターミナルの設定ではできないと思います。

この代替バージョンは、ほぼすべてのキーで停止しますが、Ctrl+ はc通常どおり機能します。

#!/bin/bash

while read -r -t 0.001; do :; done    # dump the buffer
TMP0=$(date +%s%N)
until read -r -n 1 -t 0.001; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf '\r%s' "$(($DTMP/1000000000)).${DTMP:(-9):2}"
done
echo

自分だけに反応させるには、Space読み取った内容を確認する必要があります。


until read -r -n 1 -t 0.001 && [ "$REPLY" = ' ' ]; do

Spaceスクリプトを停止するメカニズムは、 Ctrl+ のc動作とは大きく異なることに注意してください。

答え2

ストップウォッチが必要ない場合、つまり、とにかく最終的にかかった時間を知りたいだけの場合は、次のようにします。

time read -r -n 1

次のような出力が得られます:

time read -r -n 1

real    1m30.909s
user    0m0.000s
sys     0m0.000s

そして、ほぼすべてのキーストロークで停止します(Kamilの使用方法と同様read

または時間部分だけが必要な場合:

{ time read -r -n 1; } 2>&1 | grep real | awk '{ print $2 }'

提供元リシ

関連情報