是否有任何理由使用此自定义 read_char 函数而不是内置读取命令?

是否有任何理由使用此自定义 read_char 函数而不是内置读取命令?

我不擅长 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是:

  1. 前者是便携式的;它在dashbashzsh等中的工作方式相同,read -rsn1仅在bash和 中工作ksh

  2. F1当按下类似的键时,k=$(get_char)将设置为由该键 ( )k生成的整个转义符,而不是吃掉前导(Esc) 并将其留待以后使用。同样的事情也适用于任何生成多个字符的键。F1^[OP^[OP

  3. 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}
$

相关内容