トラップとUnix信号を使用してシェルからキー入力を読み取る

トラップと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
}

ベストアンサー1

local stty="$(stty -g)"

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

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

機能がSIGINT(Ctrl+を押して送信された信号C)によって中断されると、端末設定が復元され、128が返されます。 (なぜ128なのか?

stty cbreak -echo 

端末のおおよその編集機能(文字/単語/行削除)を無効にし、文字を入力するとエコーをオフにします。

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

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

ゼロ以外の状態が返されると、ddこれは読み取りエラーまたは信号がすぐに返されることを示します。端末設定は復元されません。これはエラーです。ほとんどの場合、エラーはユーザーがCtrl+を押したC場合(この場合は端末設定が復元された場合)、または端末が消えた場合(この場合、要点は議論の余地があります)です。

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

読み込まれたバイトが関数引数の文字の 1 つである場合、ループを終了します。引数が空の場合、すべての文字がループを終了します。パラメータは正確に文字リストではなく、次の場所にあります。ワイルドカード文字セット構文:初期^または逆のセット、ほとんどの位置にあるマイナス記号は範囲!(たとえば0-9)で構文解析され、[:…:]それぞれ文字クラスと組み合わせ記号を表します。バックスラッシュは以下またはを[.….]参照します。\[]-

おすすめ記事