將二進位資料貼到 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 替換字元。所以你的終端使用?預設字元)。

延伸閱讀:

相關內容