将二进制数据粘贴到 Unicode 终端中

将二进制数据粘贴到 Unicode 终端中

我需要能够将二进制数据粘贴到终端中。由于某种原因,ASCII 范围 ( 0x80- 0xff) 之外的每个字节都被粘贴为相同的三字节序列0xef 0xbf 0xbd

例如:

$ echo -en "\x80" | xclip
$ hd
<paste><EOF>
00000000  ef bf bd                                       |...|
00000004

它与终端使用的字符编码有关,因为如果我将其从 UTF-8 更改为 ISO 8859 或类似的扩展范围中的每个字符都会转换为0x3f.

有人知道如何将任意二进制数据粘贴到终端中吗?

编辑:这似乎非常依赖于终端。上面的例子是在 Konsole 中。我在 xterm 中得到了所需的行为,而 Gnome 终端根本不允许在扩展范围内粘贴字符。任何 Konsole 特定解决方案仍将受到赞赏。

答案1

ef bf bd是 UTF-8 编码替换字符(�),“用于替换其值未知或无法用 Unicode 表示的传入字符”。

你所描述的不是“扩展ASCII”,而是二进制数据。该范围内的某些字节0x80-0xff不是有效的 ISO 8859 任何内容,因此某些程序将其视为未知字符是可以理解的。

您可以尝试使用使用全部 255 个位置的 8 位字符编码,例如 IBM 代码页 850。

但是,您从中复制的程序也可能会解释数据。当您粘贴空字节或终端转义序列时会发生什么?整个方法似乎注定会失败。

答案2

终端通常不被设计为接受二进制输入:它们期望控制字符在应用程序中具有特殊含义,并对控制字符本身进行一些处理(主要是处理成一些信号)。

Emacs 的term模式(或其变体之一)是一个例外,它将粘贴的数据视为传递到应用程序的原始文本。

向应用程序提供二进制输入的正常方法是从文件或管道重定向其输入。如果数据位于 X 剪贴板中,您可以使用xclipxsel

xclip -o | myapp
xsel -o | myapp

答案3

预期的行为在这里使用矢明终端。我已经完成echo -en "\x5" | xclip,然后单击中间按钮单击屏幕会话,并在其上打开串行端口。设备如预期般发出了回声。

答案4

有一些评论没有得到合适的答案。以下是一些要点:

  • xterm 不接受“任意二进制数据”。它接受(取决于区域设置)UTF-8 或 ISO-8859-1。后者遵循 ICCM,前者是 XFree86 的扩展。在任一编码中,xterm 都可以解释这些字符以(尝试)提供选择中的数据。如果将所选内容中的 UTF-8 文本粘贴到 ISO-8859-1 编码中,它将近似最常用的字符(包括线条画)。

  • 选择(和粘贴)取决于源(进行选择的位置)和目标(粘贴文本的位置)。两者都必须就要选择/粘贴的数据的格式达成一致。 xterm 提供并接受多种格式(请参阅button.c在来源中). Konsole 和 gnome-terminal 使用较少的格式。

  • 例如,Konsole 将 X11 选择作为事后的想法。它使用QClipboard::Selection方法。 Qt 的页面评论部分X11 用户注意事项在这方面读起来很有趣。但阅读代码并看到它仅有的支持COMPOUND_TEXT

    if (*format == 8 && *type == ATOM(COMPOUND_TEXT)) {
        // convert COMPOUND_TEXT to a multibyte string
        XTextProperty textprop;
        textprop.encoding = *type;
        textprop.format = *format;
        textprop.nitems = buffer_offset;
        textprop.value = (unsigned char *) buffer->data();
    
        char **list_ret = 0;
        int count;
        if (XmbTextPropertyToTextList(display, &textprop, &list_ret,
                     &count) == Success && count && list_ret) {
            offset = buffer_offset = strlen(list_ret[0]);
            buffer->resize(offset);
            memcpy(buffer->data(), list_ret[0], offset);
        }
        if (list_ret) XFreeStringList(list_ret);
    }
    
  • 同样,GNOME 的 VTE 使用gtk_clipboard_get_for_display,通常遵循 Qt 的指导。

  • IBM 850 是一种 8 位编码(如 ISO-8859-1),不能表示 UTF-8 替换字符。所以你的终端使用?默认字符)。

进一步阅读:

相关内容