web-dev-qa-db-ja.com

トラップとUnixシグナルを使用してシェルでキー押下を読み取る

以下のスニペットのtrapと複数のstty呼び出しの目的を理解するのに問題があります。

私は誰かが私に起こっていることの概要を教えてくれることを望んでいました。

getkey() {
  local stty="$(stty -g)"
  trap "stty $stty; trap SIGINT; return 128" SIGINT
  stty cbreak -echo 
  local key
  while true; do
    key=$(dd count=1 2>/dev/null) || return $?
    if [ -z "$1" ] || [[ "$key" == [$1] ]]; then
      break
    fi
  done
  stty $stty
  echo "$key"
  return 0
}
3
Jorge Bucaran
local stty="$(stty -g)"

現在の端末設定を保存します。 stty $sttyは、関数が正常に戻ったときとSIGINTの両方で実行され、これらの設定を復元します。

trap "stty $stty; trap SIGINT; return 128" SIGINT

機能がSIGINT(を押すことによって送信される信号)によって中断された場合 Ctrl+C)、端末設定を復元して128を返します。(なぜ128なのかしら。通常、シグナルの終了ステータスは128 +シグナル番号になります。)

stty cbreak -echo 

端末の大まかな編集機能(文字/単語/行の消去)を無効にし、入力時の文字のエコーをオフにします。

  key=$(dd count=1 2>/dev/null) || return $?

端末から最大512バイトを読み取ります(countはブロック数であり、デフォルトのブロックサイズは512バイトです)。これは少し奇妙です。意図は1バイトを読み取ることだったと思います。 ddは、少なくとも1バイトが使用可能になるとすぐに返されるため、ユーザーが入力している場合、実際には1バイトが返されますが、プログラムがキーストロークをフィードしている場合、またはシステムが遅い場合は、次のようになります。より多くのバイト。このコードには、ユーザーがマルチバイト文字を入力した場合、その文字を構成するすべてのバイトがループの反復で読み取られる可能性が高い(ただし保証されない)という利点があります。

ddがゼロ以外のステータスを返す場合、これは読み取りエラーまたはシグナルを示します。関数はすぐに戻ります。端末設定が復元されないのはバグですが、ほとんどの場合、エラーはユーザーが押したもののいずれかです。 Ctrl+C、この場合、端末の設定が復元されるか、端末が消えた場合、ポイントは無効になります。

  if [ -z "$1" ] || [[ "$key" == [$1] ]]; then
    break
  fi

読み取られたバイトが関数の引数の文字の1つである場合は、ループを終了します。引数が空の場合、任意の文字でループが終了します。引数は正確には文字のリストではなく、 ワイルドカード 文字セット構文にあります。最初の^または!はセットを反転し、ほとんどの位置のマイナス記号は範囲(0-9など)として解析されます。 [:…:][.….]はそれぞれ文字クラスと照合シンボルを示し、バックスラッシュは次の\[]、または-を引用します。