Shell

使用陷阱和 Unix 信號讀取 shell 中的按鍵

  • October 9, 2015

我無法理解下面程式碼段中的目的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
}
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 字節)。這有點奇怪:我認為目的是讀取一個字節。因為dd只要至少有一個字節可用就會返回,如果使用者正在打字,這將在實踐中返回一個字節,但是如果程序正在輸入擊鍵或者係統速度很慢,這可能會讀取更多字節。該程式碼的好處是,如果使用者鍵入多字節字元,則構成該字元的所有字節都可能(但不保證)在循環迭代中被讀取。

如果dd返回非零狀態,則表示讀取錯誤或信號;該函式立即返回。終端設置未恢復,這是一個錯誤,儘管大多數情況下錯誤可能是使用者按下Ctrl+ C,在這種情況下終端設置已恢復,或者終端已消失,在這種情況下,要點是沒有實際意義。

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

如果讀取的字節是函式參數中的字元之一,則退出循環。如果參數為空,則任何字元都會終止循環。該參數不完全是字元列表,它採用萬用字元字元集語法:初始^!反轉集合,大多數位置的減號被解析為範圍(例如0-9),[:…:][.….]分別表示字元類和整理符號,以及反斜杠引用下一個\,[或.]``-

引用自:https://unix.stackexchange.com/questions/203689