解析 ANSI 转义码?

6
我正在用C#编写一个telnet应用程序(用于脚本化旧式BBS系统上的门游戏,例如Wildcat),但似乎无法构建可工作的ANSI转义码解析器(例如光标移动、着色等) - 我测试过的几乎所有系统都发送未定义的序列,这些序列违反了任何“标准”。关于此问题似乎也很少有资源,维基百科是我找到的最详细的列表,但即使他们也说它不完整 - 我遇到的大多数其他网站只是复制/粘贴了维基百科的文章。

我的问题是:是否存在相关库?如果没有,那么是否有一些解析代码/正则表达式?至少对于像ESC[!_之类的东西的适当文档将非常有帮助。

我真的觉得自己在重新发明轮子,特别是考虑到Telnet在年龄方面更或多或少相当于互联网上的轮子(;

编辑:添加了一个怪异性的示例:

00000075h: 1B 5B 73 1B 5B 32 35 35 42 1B 5B 32 35 35 43 08 ; .[s.[255B.[255C.
00000085h: 5F 1B 5B 36 6E 1B 5B 75 1B 5B 21 5F 02 02 3F 48 ; _.[6n.[u.[!_..?H
00000095h: 54 4D 4C 3F 1B 5B 30 6D 5F 1B 5B 32 4A 1B 5B 48 ; TML?.[0m_.[2J.[H
000000a5h: 0C 0D 0A                                        ; ...
The mysterious part is '21' in line 2 ---^^

适当的文档应该是ECMA-48。它涵盖了比仅仅移动光标和使事物变得丰富多彩的内容更多。 - Joey
1
由于每个终端对 ANSI 代码的处理方式不同,因此不太可能找到一个单一的规范资源,其类似于维基百科。官方参考资料是ANSI标准(维基百科链接到该标准),但这只会告诉您每个人已经同意做什么,而不是实际上做了什么。 - dimo414
1个回答

6
一个恰当的答案取决于如何使用库。任何终端仿真器都会读取这些序列并根据它们执行操作。但是,即使是简单的终端仿真器也能理解大约一百个序列。
您的示例以更易读的形式如下:
\E[s \E[255B \E[255C\t_ \E[6n \E[u \E[!_^B^B?HTML? \E[0m_ \E[2J \E[H\f\r \n
使用 unmap(将转义字符 \E 显示为可打印字符,并为转义字符开始新行)。
ECMA-48 描述了以下格式:
单字节控制字符和多字节控制序列(以转义字符开头)。
控制序列具有内容(参数),其仅限于某些字符,例如数字和分隔符,例如';'。 控制序列还有一个明确定义的结尾,称为final字符。 序列\E[! _ ^ B ^ B?不遵循这些规则。 如评论中建议的那样,也许您的录音被终端对光标位置请求\E [6n 的响应所困扰。

在这种情况下:

  • 终端仿真器执行的某些操作会修改显示(\E [2J 清除显示)
  • 终端仿真器执行的某些操作会向主机告知显示情况(\E [6n 询问终端光标的位置)
  • 终端仿真器执行的某些操作会修改终端的行为(\E [s 和\E [u 保存光标位置并稍后恢复它) 简而言之,您可以看到,要处理终端接收到的控制序列,您确实需要一个终端程序来完成所有这些操作。然而,并非所有终端仿真器都是相同的。有些使用一系列情况语句来处理转义、括号、数字等连续阶段。但是您的程序应该记住,单字节控件可能出现在多字节控制序列的中间。由于它们的编码方式不同,因此没有冲突。但是对于仅读取一个序列的程序来说,它使程序变得比您想象的更加复杂。
    xterm使用一些情况语句(基本上是最后一个字符),但在解码控制序列的大部分状态转换中,使用了一组表格。它们非常重复,但不易构造:Paul Williams指出,对于VT100,这些表格应该是对称的(基本上将输入视为7位ASCII)。某些状态被视为错误并被忽略;只有格式良好的序列才是最重要的。理论上,您可以重用状态表并添加一些“小”解析。这些表格有8500行(每行一个状态)。
    除了(a)阅读现有的终端仿真器并在较小的范围内模仿它们,或者(b)修改终端仿真器之外...您可以研究libvterm

    这是一个抽象的C99库,实现了类似VT220或xterm的终端仿真器。它不使用任何特定的图形工具包或输出系统,而是调用回调函数指针,由其嵌入程序提供绘制功能。它避免在正常运行状态下调用malloc(),使其可以在嵌入式内核环境中使用。

    然而,它不是用C#编写的(源代码就是文档)。但是,它只有5500行代码。

    进一步阅读:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接