如何设置 stty -echo 并从 /dev/stdin 读取

问题描述

我正在尝试编写一个从 stdin 读取并从 tty 接收用户输入的程序。 我想禁用用户输入的呈现,因为它会干扰我的菜单系统,并且如果我重新绘制以将其删除,则会导致闪烁。但是,如果脚本从标准输入接收输入,我似乎无法使用 stty -echo

以下是脚本的简化示例:

陷阱输入

#!/bin/bash

hideinput()
{
  if [ -t 0 ]; then
     echo "Is tty"
     save_state=$(stty -g)
     stty -echo -icanon time 0 min 0
     echo -ne "\e[?1049h\r" 1>&2;
  else
     echo "is not tty"
  fi
}

cleanup()
{
  if [ -t 0 ]; then
    stty "$save_state"
    echo -ne "\e[?1049l" 1>&2;
    echo "exit tty"
  else
    echo "is not tty"
  fi
}

trap cleanup EXIT
trap hideinput CONT
hideinput

input="$(< /dev/stdin)";
echo "$input"
while true;
do
  read -r -sn1 < /dev/tty;
  read -r -sn3 -t 0.001 k1 < /dev/tty;
  REPLY+=$k1;
  echo $REPLY
done

你好.txt

helloworld!

运行 $ ./trapinput 将在启动时回显“Is tty”,在终止时回显“exit tty”,并按照我的预期运行程序的其余部分。它还可以防止用户输入直接显示,允许我将其打印在屏幕上的正确位置。

但是,如果我运行 $ echo "test" | ./trapinput$ ./trapinput < hello.txt,它会回显“is not tty”并且未设置 stty -echo 导致用户输入显示在我不想要的地方。>

如何禁用用户输入的呈现但保留在文本/使用文件重定向中进行管道传输的能力?

解决方法

如何禁用用户输入的呈现但保留在文本/使用文件重定向中进行管道传输的能力?

禁用您从哪里获取输入的回声。做:

trap 'cleanup < /dev/tty' EXIT
trap 'hideinput < /dev/tty' CONT
hideinput </dev/tty

您还可以打开特定于输入 exec 10</dev/tty 等的文件描述符。