我不擅长 bash 和 Linux。我正在阅读脚本,发现了以下函数。
get_char()
{
SAVEDSTTY=`stty -g`
stty -echo
stty cbreak
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -raw
stty echo
stty $SAVEDSTTY
}
基本上,它用于实现按任意键继续像这样的功能。
echo "Press any key to continue!"
char=`get_char`
我知道你可以使用内置read
命令来实现这一点。例如:
read -rsn1 -p "Press any key to continue"
有什么理由使用这个函数而不是内置read
命令?
答案1
问题中的函数get_char
在生成多字节字符的键方面存在问题,并且事实上stty
作用于标准输入但从[1]dd
读取/dev/tty
,因此我将使用它的“固定”和简化版本来进行比较:
get_char(){
_g=$(stty -g); stty raw -echo; dd count=1 2>/dev/null; stty "$_g"
}
k=$(get_char)
和之间的一些区别read -rsn1 k
是:
前者是便携式的;它在
dash
、bash
、zsh
等中的工作方式相同,read -rsn1
仅在bash
和 中工作ksh
。F1
当按下类似的键时,k=$(get_char)
将设置为由该键 ( )k
生成的整个转义符,而不是吃掉前导(Esc) 并将其留待以后使用。同样的事情也适用于任何生成多个字符的键。F1
^[OP
^[
OP
Ctrl-C
(VINTR
)、Ctrl-Q
(VQUIT
) 或Ctrl-Z
(VSUSP
) 将导致k=$(get_char)
设置k
为原始控制字符(\x03
、\x11
或\x1a
),而使用 时会中断或暂停脚本read -rsn1
[2]。
[1] 如果它应该从控制 tty 读取,则可以简单地将其用作k=$(get_char </dev/tty)
[2]read -rsn1
如果脚本用 暂停Ctrl-Z
然后用 恢复,则将无法恢复 tty 设置fg
。
在带有行编辑器的 shell 中使用时的示例——它本身就扰乱了 tty 设置:
$ bash -c 'read -rsn1 foo; echo "{$foo}"'
<Ctrl-Z>
[4]+ Stopped bash -c 'read -rsn1 foo; echo "{$foo}"'
$ fg
bash -c 'read -rsn1 foo; echo "{$foo}"'
f<Enter>
{f}
$
$ bash -c 'read -rsn1 foo; echo "{$foo}"'
<Ctrl-Z>
[4]+ Stopped bash -c 'read -rsn1 foo; echo "{$foo}"'
$ fg
bash -c 'read -rsn1 foo; echo "{$foo}"'
foo<Enter>
{f}
$ oo
bash: oo: command not found
或者当从不会干扰 tty 设置的 shell 中使用时(例如dash
):
$ bash -c 'read -rsn1 foo; echo "{$foo}"'
<Ctrl-Z>
[1] + Stopped bash -c "read -rsn1 foo; echo \"{\$foo}\""
$ <Blindly type f, g, Enter>bash -c "read -rsn1 foo; echo \"{\$foo}\""
{e}
$