Ich muss in der Lage sein, binäre Daten in ein Terminal einzufügen. Aus irgendeinem Grund wird jedes Byte außerhalb des ASCII-Bereichs ( 0x80
- 0xff
) als dieselbe Drei-Byte-Sequenz eingefügt 0xef 0xbf 0xbd
.
Zum Beispiel:
$ echo -en "\x80" | xclip
$ hd
<paste><EOF>
00000000 ef bf bd |...|
00000004
Es hat etwas mit der vom Terminal verwendeten Zeichenkodierung zu tun, denn wenn ich sie von UTF-8 auf ISO 8859 oder Ähnliches ändere, wird jedes Zeichen im erweiterten Bereich in übersetzt 0x3f
.
Hat jemand eine Idee, wie man beliebige Binärdaten in das Terminal einfügt?
Bearbeiten:Dies scheint sehr terminalabhängig zu sein. Das obige Beispiel ist in Konsole. Ich erhalte das gewünschte Verhalten in xterm und Gnome Terminal erlaubt überhaupt nicht das Einfügen von Zeichen im erweiterten Bereich. Jede konsolenspezifische Lösung wäre dennoch willkommen.
Antwort1
ef bf bd
ist die UTF-8-Kodierung vonERSATZZEICHEN(�), das „verwendet wird, um ein eingehendes Zeichen zu ersetzen, dessen Wert in Unicode unbekannt oder nicht darstellbar ist“.
Was Sie beschreiben, ist kein „erweitertes ASCII“, sondern binäre Daten. Einige Bytes im Bereich 0x80
- 0xff
sind nichts gültiges ISO 8859, daher ist es verständlich, dass einige Programme das als unbekanntes Zeichen behandeln.
Sie könnten versuchen, eine 8-Bit-Zeichenkodierung zu verwenden, die alle 255 Positionen nutzt, wie etwa die IBM-Codepage 850.
Aber dann interpretiert das Programm, aus dem Sie kopieren, möglicherweise auch die Daten. Und was passiert, wenn Sie ein Nullbyte oder eine Terminal-Escape-Sequenz einfügen? Der ganze Ansatz scheint zum Scheitern verurteilt.
Antwort2
Terminals sind im Allgemeinen nicht dafür ausgelegt, binäre Eingaben zu akzeptieren: Sie gehen davon aus, dass Steuerzeichen in Anwendungen eine besondere Bedeutung haben, und verarbeiten diese teilweise selbst (meistens in einige wenige Signale).
Eine Ausnahme ist der Emacs- term
Modus (oder eine seiner Varianten), der eingefügte Daten als Rohtext behandelt, der an die Anwendung weitergegeben wird.
Die normale Methode, einer Anwendung binäre Eingaben bereitzustellen, besteht darin, die Eingaben aus einer Datei oder Pipe umzuleiten. Wenn sich die Daten in der X-Zwischenablage befinden, können Sie xclip
oder verwenden xsel
:
xclip -o | myapp
xsel -o | myapp
Antwort3
Das erwartete Verhalten funktionierte hier mitAbonnierenTerminal. Ich habe es getan echo -en "\x5" | xclip
und dann die mittlere Taste auf eine Bildschirmsitzung geklickt, auf der ein serieller Port geöffnet war. Das Gerät hat wie erwartet ein Echo ausgegeben.
Antwort4
Es gibt mehrere Kommentare, die keine passende Antwort erhalten haben. Hier sind einige Punkte:
xterm akzeptiert keine „beliebigen Binärdaten“. Es akzeptiert (je nach Gebietsschema) UTF-8 oder ISO-8859-1. Letzteres folgt dem ICCM, Ersteres ist eine Erweiterung von XFree86. In beiden Kodierungen kann xterm diese Zeichen interpretieren, um (zu versuchen) die Daten aus der Auswahl bereitzustellen. Wenn UTF-8-Text aus einer Auswahl in die ISO-8859-1-Kodierung eingefügt wird, werden die am häufigsten verwendeten Zeichen (einschließlich Linienzeichnungen) angenähert.
Auswahl (und Einfügen) hängen sowohl von der Quelle (wo die Auswahl getroffen wird) als auch vom Ziel (wo der Text eingefügt wird) ab. Beide müssen sich auf das Format der auszuwählenden/einzufügenden Daten einigen. xterm bietet und akzeptiert mehrere Formate (siehe
button.c
in Quellen). Konsole und Gnome-Terminal verwenden weniger Formate.Konsole beispielsweise führt die X11-Auswahl nachträglich durch. Es verwendet die
QClipboard::Selection
Methode. Qts Seitenkommentare im AbschnittHinweise für X11-Benutzerist in dieser Hinsicht eine interessante Lektüre. AberLesen Sie den Codeund sehen, dass esnurunterstütztCOMPOUND_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); }
Ebenso verwendet GNOMEs VTEgtk_clipboard_get_for_display, im Allgemeinen nach dem Vorbild von Qt.
IBM 850 ist eine 8-Bit-Kodierung (wie ISO-8859-1) und kann das UTF-8-Ersatzzeichen nicht darstellen. Ihr Terminal verwendet also
?
(dasStandardzeichen).
Weiterführende Literatur: