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

时间:2017-12-22 08:23:38

标签: bash zsh xterm

在xterm中运行的交互式程序可以将控制代码发送到xterm,这会导致xterm通过发回答案来响应。我想看看答案。这些控制代码中有几个,因此为了便于讨论,让我们坚持使用控制序列ESC Z,这会导致xterm发回其终端ID。例如,当我输入我的shell时(我使用Zsh,但据我所知,这也适用于bash)

echo -e '\eZ'

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

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

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

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

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

2 个答案:

答案 0 :(得分:1)

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

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

解决shell的重定向问题。

答案 1 :(得分:0)

由于我在这里没有得到任何关于这个问题的新发现,我在Unix/Linux Forums转发了问题并得到了Zsh的答案,以及对bash的改进答案,我想总结一下这里:

假设tty包含表示我的终端的字符串(这里是@ThomasDickey在他的回答中给出的建议),Zsh命令

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

将下一个单个字符读入变量REPLY。重要的是要注意-t必须被赋予超时值,并且没有字符可用的事实不能从空REPLY推导出来,而是从{{的退出代码推导出来的。 1}}命令。

至于bash,有一个比我在评论中发布的更简单的解决方案:

read

将整个回答字符串一次性读入read -rs -t 0.2 -d "" <$tty # bash ;不需要循环。