c# - 解析 ANSI 转义码?

标签 c# parsing telnet ansi-escape

我正在用 C# 构建一个 telnet 应用程序(用于在老式 BBS 系统上编写门游戏脚本,例如 Wildcat),但似乎无法为 ANSI 转义码(例如光标移动、着色等)构建一个有效的解析器 - 几乎所有我测试过的系统会发送违反任何“标准”的未定义序列。关于此事的资源似乎也很少,Wikipedia has the most in-depth list I've found so far但即使他们说它不完整 - 我遇到的大多数其他网站只是复制/粘贴维基百科的文章。

我的问题:那里有图书馆吗?如果没有,一些解析代码/正则表达式怎么样?至少一些像 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 ---^^

最佳答案

正确的答案取决于一个人打算如何使用图书馆。任何终端仿真器都将读取这些序列并根据它们执行操作。但即使是一个简单的终端仿真器也能理解大约一百个序列。

您的示例可能更易读,如下所示:

\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 保存光标位置并稍后恢复)

简而言之,您可能会看到要处理终端接收到的控制序列,您确实需要一个终端程序来完成所有这些工作。但是,并非所有终端仿真器都是相同的。有些使用一系列 case 语句来处理转义、括号、数字等的连续阶段。但是您的程序应该记住,单字节控件可以出现在多字节控制序列的中间。由于它们的编码不同,因此不存在冲突。但这会使程序比您一次只读取一个序列时想象的要复杂得多。

xterm 使用一些 case 语句(基本上用于 final 字符),但解码控制序列时的大多数状态转换都是使用一组表完成的。它们非常重复,但构造起来并不明显:Paul Williams 指出,对于 VT100,它们应该是对称的(基本上将输入视为 7 位 ASCII)。一些状态被视为错误,被忽略;无论如何,格式良好的序列才是最重要的。理论上,您可以重用状态表并添加一个“小”解析。这些表格有 8500 行(每行一个状态)。

除了 (a) 阅读现有的终端仿真器并在较小的规模上模仿它们,或 (b) 修改终端仿真器...您可以调查 libvterm :

An abstract C99 library which implements a VT220 or xterm-like terminal emulator. It doesn't use any particular graphics toolkit or output system, instead it invokes callback function pointers that its embedding program should provide it to draw on its behalf. It avoids calling malloc() during normal running state, allowing it to be used in embedded kernel situations.

但是,这不是在 C# 中(源代码文档)。不过,它只有 5500 行代码。

进一步阅读:

关于c# - 解析 ANSI 转义码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4097311/

相关文章:

java - 是否有任何工具可以从 Java 中的英文文本或文章中提取关键字?

php - SMTP Telnet和PHP无法从HELO中获得任何响应

linux - 远程登录本地主机

c# - WPF 绑定(bind) ItemsControl 中的字符串值列表

c# - Java 事务 API 和 .NET System.Transactions

java - 命题逻辑程序中括号的解析

c - 如何用C实现一个简单的telnet客户端向服务器发送命令

c# - 读取 DTD 或 Schema 并列出给定元素的所有有效子元素或属性

c# - 到底什么是 String.LegacyMode 属性?

iphone - 从 CLLocation 数组创建 GPX 文件