Shell-Script
我可以在 POSIX shell 中從標準輸入讀取單個字元嗎?
僅
read -r
由POSIX 指定;read -n NUM
,用於讀取NUM
字元,不是。從標準輸入讀取給定數量的字元後,是否有一種可移植的方式自動返回?我的案例正在列印這樣的提示:
Do the thing? [y/n]
如果可能的話,我想讓程序在輸入
y
or後自動繼續n
,而不需要使用者在之後按 enter。
讀取一個字元意味著一次讀取一個字節,直到你得到一個完整的字元。
要使用 POSIX 工具箱讀取一個字節,有
dd bs=1 count=1
.但是請注意,從終端設備讀取時,當該設備處於
icanon
模式時(通常預設情況下),只有在您按下Return
(akaEnter
) 時才會返回,因為在此之前終端設備驅動程序實現了一種行編輯器形式,允許您使用Backspace
或其他編輯字元來修改您輸入的內容,並且您輸入的內容僅在您送出您一直在編輯的那一行時才可用於閱讀應用程序(使用Return
或Ctrl
+D
)。出於這個原因,
ksh
’sread -n/N
或zsh
’sread -k
,當他們檢測到 stdin 是終端設備時,將該設備置於icanon
模式之外,以便在終端發送字節後立即可以讀取它們。現在請注意
ksh
’read -n n
只讀取一行**中的n
字元,當讀取換行符時它仍然停止(用於讀取字元)。,與 ksh93 相反,仍然對 和 進行 IFS 和反斜杠處理。-N n``n``bash``-n``-N
要模仿
zsh
’sread -k
或ksh93
’sread -N1
或bash
’sIFS= read -rN 1
,即從標準輸入中讀取一個且僅一個字元,POSIXly:readc() { # arg: <variable-name> if [ -t 0 ]; then # if stdin is a tty device, put it out of icanon, set min and # time to sane value, but don't otherwise touch other input or # or local settings (echo, isig, icrnl...). Take a backup of the # previous settings beforehand. saved_tty_settings=$(stty -g) stty -icanon min 1 time 0 fi eval "$1=" while # read one byte, using a work around for the fact that command # substitution strips the last character. c=$(dd bs=1 count=1 2> /dev/null; echo .) c=${c%.} # break out of the loop on empty input (eof) or if a full character # has been accumulated in the output variable (using "wc -m" to count # the number of characters). [ -n "$c" ] && eval "$1=\${$1}"'$c [ "$(($(printf %s "${'"$1"'}" | wc -m)))" -eq 0 ]'; do continue done if [ -t 0 ]; then # restore settings saved earlier if stdin is a tty device. stty "$saved_tty_settings" fi }