在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 命令。但是,如果我想一次读取一个字符的回答字符串,我确实需要一个循环。
有人可以解释一下,为什么我的方法失败了,以及我如何解决我的问题?
答案 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
;不需要循环。