在\u有效的shell中(bash +4.3、ksh93或zsh),我们可以打印Unicode字符:
$ printf 'a b c \ua0 \ua1 \ua2 \ua3 \n'
a b c ¡ ¢ £这是来自拉丁文-1_补充范围的一些字符。
但是,一旦添加了Unicode 9f字符,打印就会停止,直到打印Unicode 9c为止。
\u9f和\u9c (APC和ST)都是C1控制字符。
$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n'
a b c ¡ ¢ £ 角色就消失了。
可以肯定的是,printf正在生成所有字符,并且将输出重定向到其他软件(而不是终端)将显示生成的字符:
$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n' | od -A n -tx1
61 20 62 20 63 20 c2 9f 20 64 20 65 20 66 20 c2
9c 20 c2 a0 20 c2 a1 20 c2 a2 20 c2 a3 20 0a这甚至可以证明字符是生成的。那麽,为何不印(用可见的字形显示)呢?
我要问的问题是:
APC是否真的连接到ST。它的定义在哪里?编辑
xterm和konsole终端都不删除d e f字符。
这证实了这是终端应用程序的内部问题,而不是shell。还没有找到定义的位置。
发布于 2022-07-10 11:43:55
装甲运兵车真的和ST有联系吗。它的定义在哪里?
这些控制字符实际上并不是Unicode的原始字符,而是继承自较早的字符集规范,如ECMA-48、ISO/IEC 6429和ISO/IEC-8859系列字符编码。一般说来,这些标准在C1控制字符上基本上是一致的(因为它们是向后兼容的,有些甚至是更旧的规范)。
由于ISO/IEC 6429的副本正在销售中,我不希望在互联网上找到它的合法副本,但ECMA-48说:
8.3.2 APC -应用程序命令表示法:(C1)表示: 09/15或ESC 05/15 APC用作应用程序使用的控制字符串的开始分隔符。下面的命令字符串可以由范围为00/08至00/13和02/00至07/14的位组合组成。控制字符串由终止分隔符字符串终止符(ST)关闭。命令字符串的解释取决于相关的应用程序。
以及:
8.3.143 ST - STRING终止符表示法:(C1)表示: 09/12或ESC 05/12 ST用作应用程序命令、设备控制字符串、操作系统命令、隐私消息(PM)或字符串启动(SOS)打开的控制字符串的结束分隔符。
Unicode只在C1控制字符范围内定义一个控制字符: U+0085下一行(NEL)。对于C1范围内的任何其他字符,规范的这一部分应用:
控制码的语义一般由使用它们的应用程序决定。但是,如果没有特定的应用程序使用,则可以根据ISO/IEC 6429:1992中指定的控制函数语义来解释它们。
我不能在这里验证它,但我希望ISO/IEC 6429非常接近于ECMA-48所说的,如前所述。此外,终端的作者可能会认为“向后兼容前Unicode 7位和8位字符编码,如ECMA-48”是一种特定的应用用途。
因此,终端可能会合法地将APC和ST之间的字符解释为“我不知道这些字符是干什么用的,但我肯定知道这些字符并不打算显示为常规输出。”
终端可能会或不可能以某种方式对封装在APC和ST之间的特定字符串做出反应,而忽略任何不匹配的字符串。由于终端窗口是“人类之前的最后一步”,因此可以肯定地假定到达该窗口的任何应用程序命令字符串都意味着终端可以解释并对其进行操作,而终端无法识别的任何此类字符串都必须是错误。
显示“无效编码”字符或其他错误消息是不合适的,因为字符串被有效地编码为“特定于应用程序的控制字符串,用于显示的not”。所以,这个标题问题的答案是:“角色们要去哪里?”最有可能的情况是:<#>they作为无效控件字符串的一部分被丢弃。
但是请注意,Unicode规范说“.可以进行解释.”,而不是“.<#>必须解释.”。因此,其他终端实现的选择,仅仅忽略APC和ST字符作为不可打印控制字符,没有适用的意义,也不一定是无效的。
关于堆栈溢出的问题还讨论了涉及APC和ST控制字符的控制序列。
那里被接受的答案是:
实际情况是,APC很少实现--大多数系统从来不生成APC序列,并且默默地忽略任何接收到的内容。任何应用程序都不应发送或解释APC序列,除非它知道连接的另一端正在以特定的方式使用它们,例如通过配置选项启用它们,或者(不知怎么地)它知道使用的是哪个终端模拟器,并且知道终端模拟器为它们指定了特定的含义。
发布于 2022-07-10 10:52:36
字符没有被发送到任何地方,它们只是没有被终端显示,尽管它们在输出中:
$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n' | od -c
0000000 a b c 302 237 d e f 302
0000020 234 302 240 302 241 302 242 302 243 \n
0000037您还可以通过重定向到一个文件,然后调查该文件来确认它们在输出中:
$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n' > file
$ od -c file
0000000 a b c 302 237 d e f 302
0000020 234 302 240 302 241 302 242 302 243 \n
0000037看来,终端对\u9f和\u9c组合所做的事情是依赖于实现的。很简单,终端处理它的方式是向后移动几个字符,然后从那里继续打印,这会导致覆盖其他字符。这就是为什么你看到:
$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n'
a b c ¡ ¢ £ 我可以在gnome-terminator上复制它,但是xterm只打印一个空格:
$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n'
a b c d e f ¡ ¢ £ 截图中也有一样的东西:

这类似于在更明确的情况下发生的情况,即使用马车回程 (\r),它的工作就是将代码移回行的开头。这就是为什么你会:
$ printf '12345\r67890\n'
67890终端开始打印12345,然后\r将其发送回行的开头,在该行中,它用67890覆盖12345,所以您最后看到的只有67890。但是132345没有发送到任何其他程序,它仍然在那里,因为其他字符覆盖了它,所以它是不可见的:
$ printf '12345\r67890\n' | od -c
0000000 1 2 3 4 5 \r 6 7 8 9 0 \n
0000014发布于 2022-07-09 12:29:28
您正在解释输出UTF8字符序列的命令以及在终端模拟器窗口(通常称为“我的终端窗口”)中显示的结果。
然后,您将描述似乎不会导致在终端模拟器窗口中显示可见结果的字符序列。你会问,“这些字符是否被发送到某个应用程序中?”
是的,它们被传递到您的终端仿真器,它解释它接收到的字符序列,并决定它将在其窗口中显示哪些符号供您查看。
https://unix.stackexchange.com/questions/709189
复制相似问题