Bash 读取发送到xterm的控制字符串的应答

Bash 读取发送到xterm的控制字符串的应答,bash,zsh,xterm,Bash,Zsh,Xterm,在xterm中运行的交互式程序可以向xterm发送控制代码,从而使xterm通过返回答案来响应。我想读一下答案。其中有几个控制代码,为了便于讨论,让我们继续使用控制序列ESC Z,它会导致xterm返回其终端id。例如,当我在shell中键入时(我使用的是Zsh,但据我所知,这也适用于bash) 我在终端缓冲区中看到字符串 63;1;2;4;6;9;15;22;29c 并听到一声蜂鸣声(因为从xterm发送的答案还包含不可打印的字符,特别是它还包含ESC)。我的目标是以某种方式阅读这个字符串6

在xterm中运行的交互式程序可以向xterm发送控制代码,从而使xterm通过返回答案来响应。我想读一下答案。其中有几个控制代码,为了便于讨论,让我们继续使用控制序列ESC Z,它会导致xterm返回其终端id。例如,当我在shell中键入时(我使用的是Zsh,但据我所知,这也适用于bash)

我在终端缓冲区中看到字符串

63;1;2;4;6;9;15;22;29c
并听到一声蜂鸣声(因为从xterm发送的答案还包含不可打印的字符,特别是它还包含ESC)。我的目标是以某种方式阅读这个字符串63;1.2.4.6.9;15;22;29c转换为shell变量我主要使用Zsh,但也欢迎使用bash(或任何其他脚本语言,如Ruby、Perl或Python)的解决方案。

我的第一次尝试非常简单:

#!/bin/zsh
echo -e '\eZ'
read -rs -k 25
echo $REPLY | xxd
这是可行的,因为我发现(经过一点尝试和错误)在我的特定xterm上的这个特定示例中,应答字符串的长度为25个字符。当然,在一般情况下,我事先不知道确切的长度,所以我想要一个更灵活的解决方案。我的想法是一次读一个字符,直到什么都不剩,我编写了以下程序来测试我的想法:

#!/bin/zsh
str=''
echo -e '\eZ'
while :
do
  read -rs -t -k
  if [[ -z $REPLY ]]
  then
    echo '(all read)'
    break
  fi
  str="${str}$REPLY"
完成 echo$str | xxd

然而,这并没有读到任何东西。回复总是空的

我还尝试了变体
read-rs-t-k1
(效果相同)和
read-rs-k1
(永远挂起)。即使是
read-rsk25
也不能再工作了,所以我猜罪魁祸首是while循环,而不是read命令。但是,如果我想一次读取一个字符的应答字符串,我确实需要一个循环


有人能解释一下,为什么我的方法失败了,以及我如何解决我的问题吗?

您可以让read语句直接从终端读取,例如

read -rs -t -k < $(tty)
read-rs-t-k<$(tty)

为了解决shell的重定向问题。

因为我在这里没有关于这个问题的任何新发现,所以我在上交叉发布了这个问题,并收到了Zsh的答案和bash的改进答案,我想在这里总结一下:

假设
tty
包含表示我的终端的字符串(以下是@ThomasDickey在其答案中给出的建议),则Zsh命令

read -rs -t 0.2 -k 1 <$tty # zsh

整个应答字符串一次读入
应答
;不需要循环。

我将示例脚本中的
read
命令替换为您建议的命令,但在我的zsh版本(5.3)中,这也不起作用(同样,只读取了一个字符)。然而,我试图把你的想法转给bash。对于bash,等效的命令是
read-rs-t1-n1<$(tty)
,这确实完成了任务!整个答案字符串被读取!!!在这方面,这回答了我的问题,但我还没有将其标记为“已回答”,而是将其保留几天,以防有人也在Zsh中提出解决方案。
read -rs -t 0.2 -k 1 <$tty # zsh
read -rs -t 0.2 -d "" <$tty # bash