AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 709189
Accepted
QuartzCristal
QuartzCristal
Asked: 2022-07-09 17:58:17 +0800 CST2022-07-09 17:58:17 +0800 CST 2022-07-09 17:58:17 +0800 CST

人物去哪儿了?

  • 772

在\u有效的 shell(bash +4.3、ksh93 或 zsh)中,我们可以打印 Unicode 字符:

$ printf 'a b c \ua0 \ua1 \ua2 \ua3 \n'
a b c   ¡ ¢ £

这是来自Latin-1_Supplement范围的一些字符。

但是,一旦9f添加了 Unicode 字符,打印就会停止,直到 Unicode9c被打印出来。

\u9f和\u9c(APC 和 ST) 都是控制C1字符。

$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n'
a b c    ¡ ¢ £ 

字符 def 消失。

可以肯定的是,它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

这足以证明正在生成字符。那么,为什么它们没有被打印(显示有一些可见的字形)?

我的问题是:

  1. 实际上是APC连接到ST。它在哪里定义?
  2. 这两个字符之间的字符是否发送到某个应用程序?
  3. 如果是这样,适用于哪个应用程序?
  4. 谁负责这种重定向?外壳,终端或其他东西?

编辑

和终端都xterm不会konsole删除d e f字符。

这证实这是终端应用程序的内部问题,而不是外壳。还没有找到定义的地方。

bash shell
  • 3 3 个回答
  • 189 Views

3 个回答

  • Voted
  1. Best Answer
    telcoM
    2022-07-11T03:43:55+08:002022-07-11T03:43:55+08:00

    APC 是否实际连接到 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 范围内的位组合组成。控制字符串由终止分隔符 STRING TERMINATOR (ST) 关闭。命令字符串的解释取决于相关的应用程序。

    和:

    8.3.143 ST - 字符串终止符

    符号:(C1)

    表示:09/12 或 ESC 05/12

    ST 用作由应用程序命令 (APC)、设备控制字符串 (DCS)、操作系统命令 (OSC)、隐私消息 (PM) 或字符串开始 (SOS) 打开的控制字符串的结束分隔符。

    Unicode 在 C1 控制字符范围内只定义了一个控制字符:U+0085 Next Line (NEL)。对于 C1 范围内的任何其他字符,规范的这一部分适用:

    控制代码的语义通常由使用它们的应用程序确定。但是,在没有特定应用用途的情况下,可以根据 ISO/IEC 6429:1992 中规定的控制功能语义来解释它们。

    我无法在这里验证它,但我希望 ISO/IEC 6429 与 ECMA-48 所说的非常接近,如上所述。此外,终端的作者可能认为“向后兼容 pre-Unicode 7 位和 8 位字符编码,如 ECMA-48”是一种特定的应用程序用途。

    因此,终端可能会合法地将 APC 和 ST 之间的字符解释为“我不知道这些是做什么用的,但我肯定知道这些不打算显示为常规输出。”

    终端可能会或可能不会以某种方式对封装在 APC 和 ST 之间的特定字符串做出反应,并忽略任何不匹配的字符串。由于终端窗口是“人类之前的最后一步”,它当然可以假设任何到达它的应用程序命令字符串都是为了让终端解释和操作(如果适用),以及任何无法识别的此类字符串由终端必须是错误的。

    显示“无效编码”字符或其他错误消息是不合适的,因为该字符串被有效地编码为“特定于应用程序的控制字符串,而不是用于显示”。因此,对于题为“角色要去哪里?”的问题的答案。最有可能:它们作为无效控制字符串的一部分被丢弃。

    但请注意,Unicode 规范说“......可能被解释......”,而不是“......必须被解释......”。因此,其他终端实现选择只是将APC和ST字符作为没有适用意义的不可打印控制字符忽略也不一定是无效的。

    Stack Overflow 上的这个问题还讨论了涉及 APC 和 ST 控制字符的控制序列。

    那里接受的答案说:

    现实情况是,APC 很少被实施——大多数系统从不生成 APC 序列并默默地忽略任何接收到的序列。任何应用程序都不应发送或解释 APC 序列,除非它知道连接的另一端正在以特定方式使用它们——例如通过配置选项启用它们,或者如果它(以某种方式)知道正在使用哪个终端仿真器,并且知道终端仿真器赋予它们特定的含义 [...]

    • 4
  2. terdon
    2022-07-11T02:52:36+08:002022-07-11T02:52:36+08:00

    这些字符没有被发送到任何地方,尽管它们在输出中,但它们根本没有被您的终端显示:

    $ 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    ¡ ¢ £ 
    

    以下是屏幕截图中的相同内容:

    显示 xterm 和 gnome-terminal 中不同输出的屏幕截图

    这类似于在一个更明确的情况下发生的情况,即使用回车符( \r),其工作就是回到行首。这就是为什么你得到:

    $ printf '12345\r67890\n'
    67890
    

    终端开始打印12345,然后将其\r发送回行的开头,在那里它用 覆盖了12345,67890所以您最终看到的只是67890. 但是132345没有发送到任何其他程序,它仍然存在,它根本不可见,因为其他字符已经覆盖了它:

    $ printf '12345\r67890\n' | od -c
    0000000   1   2   3   4   5  \r   6   7   8   9   0  \n
    0000014
    
    • 1
  3. Sotto Voce
    2022-07-10T04:29:28+08:002022-07-10T04:29:28+08:00

    您正在解释输出 UTF8 字符序列的命令以及您在终端模拟器窗口(通常称为“我的终端窗口”)中看到的结果。

    然后,您描述似乎不会导致在终端仿真器窗口中显示可见结果的字符序列。你问,“字符是否被发送到某个应用程序?”

    是的,它们被传送到您的终端仿真器,它解释它接收到的字符序列并决定它将在其窗口中显示哪些字形供您查看。

    • -1

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • 如何将带有〜的路径保存到变量中?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve