读取发送到 xterm 的控制字符串的答案
Reading answer to control string sent to 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"
完成
回声 $海峡 | xxd
然而,这并没有读取任何内容。回复总是空的。
我还尝试了变体 read -rs -t -k 1
(同样的效果)和 read -rs -k 1
(永远挂起)。甚至 read -rs k 25
也不再起作用,所以我猜罪魁祸首是 while 循环,而不是 read 命令。但是,如果我想一次读取一个字符的应答字符串,我确实需要一个循环。
有人可以解释一下为什么我的方法失败了,我该如何解决我的问题?
您可以直接从终端读取 read-statement,例如,
read -rs -t -k < $(tty)
解决 shell 的重定向问题。
因为我在这里没有得到关于这个问题的任何新发现,所以我在 Unix/Linux Forums 交叉发布了这个问题并收到了 Zsh 的答案,以及 bash 的改进答案,我想在这里总结一下:
假设 tty
包含表示我的终端的字符串(这里遵循@ThomasDickey 在他的回答中给出的建议),Zsh-command
read -rs -t 0.2 -k 1 <$tty # zsh
将下一个单个字符读入变量REPLY
。重要的是要注意 -t
必须被赋予一个超时值,事实上,没有字符可用,不能从空的 REPLY
中推断出来,而是从 [= 的退出代码中推断出来16=]命令。
至于 bash,有一个比我在评论中发布的解决方案更简单的解决方案:With
read -rs -t 0.2 -d "" <$tty # bash
整个回复字符串一次性读入REPLY
;不需要循环。
整理一下这里的答案,成品如下:
#!/usr/bin/env bash
tty=/dev/tty
cat >$tty
read -rs -t 0.2 -d "" <$tty
echo $REPLY | xxd -r -p
$ printf '\eP+q544e\e\' | escape_code_answer_read.bash
TNxterm-kitty
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"
完成 回声 $海峡 | xxd
然而,这并没有读取任何内容。回复总是空的。
我还尝试了变体 read -rs -t -k 1
(同样的效果)和 read -rs -k 1
(永远挂起)。甚至 read -rs k 25
也不再起作用,所以我猜罪魁祸首是 while 循环,而不是 read 命令。但是,如果我想一次读取一个字符的应答字符串,我确实需要一个循环。
有人可以解释一下为什么我的方法失败了,我该如何解决我的问题?
您可以直接从终端读取 read-statement,例如,
read -rs -t -k < $(tty)
解决 shell 的重定向问题。
因为我在这里没有得到关于这个问题的任何新发现,所以我在 Unix/Linux Forums 交叉发布了这个问题并收到了 Zsh 的答案,以及 bash 的改进答案,我想在这里总结一下:
假设 tty
包含表示我的终端的字符串(这里遵循@ThomasDickey 在他的回答中给出的建议),Zsh-command
read -rs -t 0.2 -k 1 <$tty # zsh
将下一个单个字符读入变量REPLY
。重要的是要注意 -t
必须被赋予一个超时值,事实上,没有字符可用,不能从空的 REPLY
中推断出来,而是从 [= 的退出代码中推断出来16=]命令。
至于 bash,有一个比我在评论中发布的解决方案更简单的解决方案:With
read -rs -t 0.2 -d "" <$tty # bash
整个回复字符串一次性读入REPLY
;不需要循环。
整理一下这里的答案,成品如下:
#!/usr/bin/env bash
tty=/dev/tty
cat >$tty
read -rs -t 0.2 -d "" <$tty
echo $REPLY | xxd -r -p
$ printf '\eP+q544e\e\' | escape_code_answer_read.bash
TNxterm-kitty