解析 ANSI 转义码?

2024-01-08

我正在用 C# 构建一个 telnet 应用程序(用于在老式 BBS 系统上编写门游戏脚本,例如 Wildcat),但似乎无法为 ANSI 转义码(例如光标移动、着色等)构建一个可用的解析器 - 几乎所有系统我'已经测试过发送不符合任何“标准”的未定义序列。关于这个问题的资源似乎也很少,维基百科有我迄今为止找到的最深入的列表 http://en.wikipedia.org/wiki/ANSI_escape_code但即使他们说它不完整 - 而且我遇到的大多数其他网站只是复制/粘贴维基百科的文章。

我的问题:那里有图书馆吗?如果没有,一些解析代码/正则表达式怎么样?至少有一些适当的文档,例如ESC[!_将会非常有帮助。

我真的觉得我正在重新发明轮子,特别是看到 Telnet 或多或少相当于互联网的轮子(至少在年龄方面是这样;)

EDIT:添加了一个奇怪的例子:

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 ---^^

正确的答案取决于人们打算如何使用该库。任何终端模拟器都会read那些序列和perform基于它们的行动。但即使是一个简单的终端模拟器也能理解大约一百个序列。

您的示例以可能更具可读性的形式如下所示:



\E[s
\E[255B
\E[255C\t_
\E[6n
\E[u
\E[!_^B^B?HTML?
\E[0m_
\E[2J
\E[H\f\r
\n
  

using unmap http://invisible-island.net/misc_tools/index.html#item:unmap(制作转义字符\E并展示all可打印的字符 - 并为转义字符开始一个新行)。

ECMA-48 描述了以下格式

  • 单字节控制字符,以及
  • 多字节控制序列(以转义字符开头)。

控制序列的内容(参数)仅限于某些字符,例如数字和分隔符,例如,';'。控制序列也有一个明确的结局,称为final特点。序列\E[!_^B^B?不遵守这些规则。正如评论中所建议的,也许您的录音因终端对光标位置请求的响应而混淆\E[6n.

有了这么多背景:

  • 终端仿真器执行的一些操作会修改显示(\E[2J清除显示)
  • 终端仿真器执行的一些操作告诉主机about显示器 (\E[6n询问终端光标在哪里is)
  • 终端仿真器执行的一些操作会修改终端的行为(\E[s and \E[u保存光标位置并稍后恢复)

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

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

除了(a)读取现有的终端模拟器并在较小范围内模仿它们,或(b)修改终端模拟器......您可以调查libvterm http://www.leonerd.org.uk/code/libvterm/:

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

然而,这并不在C#(以及来源is文档)。尽管如此,它也只有 5500 行代码。

进一步阅读:

  • 通过计数控件来比较版本 http://invisible-island.net/xterm/xterm.faq.html#compare_versions
  • XTerm 控制序列 http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
  • DEC ANSI 兼容视频终端的解析器 http://vt100.net/emu/dec_ansi_parser
  • ECMA-48:编码字符集的控制函数 http://www.ecma-international.org/publications/standards/Ecma-048.htm
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解析 ANSI 转义码? 的相关文章

  • 金特 + XNA (C#)

    是否可以使用jint http jint codeplex com操作使用 XNA C 创建的 3D 环境 并向该环境添加功能 再次使用 jint 作为 Jint 的贡献者 我会推荐你Jint http jint codeplex com
  • Volatile.Read 和 Volatile.Write 背后的逻辑是什么?

    来自 MSDN Volatile Read 读取字段的值 在需要它的系统上 插入一个 阻止处理器重新排序内存的内存屏障 操作如下 如果在该方法之后出现读或写 代码 处理器无法移动它before这个方法 and Volatile Write
  • 编写此代码片段的有效方法是什么? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 更有效和 或更短地重写此代码以节省字节并显得不那么冗长的方法 if N 2 0 N 6 N 8 N 10 N 12 N 14 N 16 N
  • 在 C# 中使用“using”关键字避免多次处置的最佳实践

    当变量是 IDisposable 时 我们有using关键字来管理处置 但是如果我们在方法中返回值怎么办 using twice StringContent stringToStringContent string str using St
  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • 我如何知道 C 程序的可执行文件是在前台还是后台运行?

    在我的 C 程序中 我想知道我的可执行文件是否像这样在前台运行 a out 或者像这样 a out 如果你是前台工作 getpgrp tcgetpgrp STDOUT FILENO or STDIN FILENO or STDERR FIL
  • MFC CList 支持复制分配吗?

    我在 MSVC 中查找了 CList 定义afxtempl h http www cppdoc com example mfc classdoc MFC AFXTEMPL H html并记录在MSDN http msdn microsoft
  • 如果 JSON.NET 中的值为 null 或空格,则防止序列化

    我有一个对象需要以这样的方式序列化 即 null 和 空白 空或只是空格 值都不会序列化 我不控制对象本身 因此无法设置属性 但我知道所有属性都是字符串 环境NullValueHandling显然 忽略 只能让我找到解决方案的一部分 它 似
  • 司机和提供商之间的区别

    数据库中的驱动程序和提供程序有什么区别 有没有解释一下 不胜感激 样本 ADO NET driver for MySQL vs providerName System Data EntityClient 来自 MSDN 论坛 驱动程序是安装
  • C# 处理标准输入

    我目前正在尝试通过命令行断开与网络文件夹的连接 并使用以下代码 System Diagnostics Process process2 new System Diagnostics Process System Diagnostics Pr
  • C++ 将联合强制转换为其成员类型之一

    以下对我来说似乎完全符合逻辑 但不是有效的 C 联合不能隐式转换为其成员类型之一 有人知道为什么不这样做的充分理由吗 union u int i char c function f int i int main u v v i 6 f v
  • while循环中的变量初始化

    我有一个可以分块读取文件的函数 public static DataObject ReadNextFile 数据对象看起来像这样 public DataObject public string Category get set And ot
  • 将日期时间转换为指定格式

    我有这个日期格式yy MM dd HH mm ss ex 12 02 21 10 56 09 问题是 当我尝试使用以下代码将其转换为不同格式时 CDate 12 02 21 10 56 09 ToString MMM dd yyyy HH
  • 如何在 C# 中获取 Json 数组?

    我有一个像这样的 Json 字符串 我想将它加载到 C 数组中 当我尝试这样做时 我收到异常 我的字符串 customerInformation customerId 123 CustomerName Age 39 Gender Male
  • C++ 到 C# 事件处理

    所以我有我的C WinForm 应用程序 我从中调用我的C CLI MFC dll图书馆 但也有一些events在我的 C 库上 甚至此事件也发生在该库的本机 非 CLI 部分 我需要从我的 C 应用程序调用一些代码 并获取一些有关此事件的
  • 使用多线程进行矩阵乘法?

    我应该使用线程将两个矩阵相乘 有两件事 当我运行程序时 我不断得到 0 我还收到消息错误 对于每个错误 它在粗体行上显示 警告 从不兼容的指针类型传递 printMatrix 的参数1 我尝试打印输出 还要注意 第一个粗体块 这是我解决问题
  • C# 中的 C/C++ 代码编译器

    在 C 中 我可以使用下面的代码编译 VB 和 C 代码 但无法编译 C C 代码 有什么办法可以做到这一点吗 C 编译器 public void Compile string ToCompile string Result null st
  • 使用 xslt 将 xml 转换为 xsl-fo 时动态创建超链接?

    我想使用 xsl 文件在 PDF 报告中创建标题 如果源文件包含超链接 则应将其呈现为超链接 否则呈现为纯文本 例如 我的 xml 如下所示 a href http google com target blank This is the h
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟
  • 如何在dll级别读取app.config? [复制]

    这个问题在这里已经有答案了 我在一个解决方案中有一个控制台应用程序项目和库项目 dll The 图书馆项目有 app config 文件 我在其中存储我在库中使用的一些键值对 控制台应用程序引用此 dll 我有另一个 app config

随机推荐