代码之家  ›  专栏  ›  技术社区  ›  user1934428

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

  •  3
  • user1934428  · 技术社区  · 7 年前

    在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;29摄氏度 转换为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"
    

    完成 回声$str | xxd

    然而,这并没有读取任何内容。答复始终为空。

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

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

    3 回复  |  直到 7 年前
        1
  •  2
  •   Thomas Dickey    7 年前

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

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

    解决shell重定向问题。

        2
  •  2
  •   user1934428    7 年前

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

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

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

    将下一个字符读入变量 REPLY . 需要注意的是 -t 必须给定超时值,并且不能从空 答复: ,但从 read 命令

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

    read -rs -t 0.2 -d "" <$tty # bash
    

    整个应答字符串作为一次读入 答复: ; 无需循环。

        3
  •  0
  •   HappyFace    3 年前

    把答案放在一起,这里是成品:

    #!/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