Shell
使用陷阱和 Unix 信號讀取 shell 中的按鍵
我無法理解下面程式碼段中的目的
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
),[:…:]
並[.….]
分別表示字元類和整理符號,以及反斜杠引用下一個\
,[
或.]``-