Warum ist das Einheitentrennzeichen (ASCII 31) in der Terminalausgabe unsichtbar?

Warum ist das Einheitentrennzeichen (ASCII 31) in der Terminalausgabe unsichtbar?

Das ASCII-Zeichen (ASCII 31, Oktal 37) als Einheitentrennzeichen ist in Vim als sichtbar ^_. Wenn ich jedoch dieselbe Datei auf dem Terminal drucke, ist das Zeichen unsichtbar. Dies führt dazu, dass die Felder in einer Zeile aneinander kleben bleiben:

# In Vim and less:

first field^_second field^_last field

# cat the same file to terminal:
cat delim.txt
first fieldsecond fieldlast field

# print 2nd field with awk 
cat delim.txt | awk 'BEGIN {FS = "\037"} {print $2}'
second field

Ich nehme an, dass ich den Einheitentrenner mit cat -v sichtbar machen kann:

cat -v delim.txt
first field^_second field^_last field

Das ist aber ziemlich umständlich. Warum wird der Einheitentrenner nicht sichtbar dargestellt, wenn er in der Bash-Shell auf stdout gedruckt wird? Ich kann die Shell-Ausgabe nicht einmal richtig kopieren und einfügen; der Einheitentrenner geht dabei verloren.

Antwort1

Das Einheitentrennzeichen ( US), auch bekannt als IS1, gehört zur cntrlZeichenklasse und istnichtin der printZeichenklasse. Es ist ein Steuerzeichen, das dazu dient, Text in Gruppen zu gliedern,für Programme, die diese Informationen nutzen sollenIm Allgemeinen werden nicht druckbare Zeichen in verschiedenen Programmen oder Umgebungen wahrscheinlich unterschiedlich interpretiert und wiedergegeben.

Der Grund, warum Sie es als in Vim dargestellt sehen, ^_ist, dass Vim ein interaktiver Editor ist. Er kann nicht druckbare Zeichen beliebig darstellen, solange das richtige Binärzeichen auf die Festplatte geschrieben wird.

Dasselbe Verhalten können Sie in der Shell nicht erreichen, da Unix-Shell-Programme so geschrieben sind, dass sie Klartext verarbeiten und untereinander weitergeben. Wenn Sie cateine Datei haben, muss der Text, der in das Terminal geschrieben wird, dem entsprechen, was tatsächlich in der Datei steht.

Somit bleibt es dem Endgerät überlassen, das Zeichen zu interpretieren. Und es stellt sich heraus, dass einige TerminalemulatorenTunrendern das USZeichen anders als andere. In gnome-terminal(oder jedem vte-basierten Terminal) wird das Zeichen als Feld mit dem Hex-Code gerendert 001F. In xtermoder rxvtist das Zeichen tatsächlich unsichtbar.

Antwort2

Das Einheitentrennzeichen liegt im ASCII-Bereich vonSteuerzeichen, und hat daher (oder sollte normalerweise) keine visuelle Darstellung.

Vim und einige andere Editoren zeigen sie an, sodass Sie sie bearbeiten können. Wie Sie bemerkt haben, cat -vzeigt es auch an. Die Manpage zeigt, dass es -vsich dabei um die Kurzform von handelt --show-nonprinting, die dazu führt, dass die nicht druckbaren Zeichen durch eine druckbare Darstellung ersetzt werden, die nicht dem ursprünglichen Inhalt der Datei entspricht und daher Probleme verursachen kann, wenn die Ausgabe tatsächlich an ein anderes Programm geht.

Die Darstellung, die Sie sehen, deutet bereits darauf hin, dass es sich um ein Steuerzeichen handelt: Ein Zeichen, dem ein a vorangestellt ist, ^ist eine gängige Notation für Ctrl+ das Zeichen, also die Tastenkombination, die dieses Zeichen in einem Terminal erzeugt. Ctrl+ _ermöglicht Ihnen beispielsweise die Eingabe des Einheitentrennzeichens in vim. Ein anderer Editor oder ein GUI-Viewer zeigt jedoch möglicherweise den Hex-Code, einen Platzhalter oder etwas völlig anderes an.

Da Ihr Terminal die Steuerzeichen nicht druckt, werden diese auch beim Markieren des Textes nicht kopiert (eine Ausnahme bilden hier die Whitespace-Zeichen wie Newline und Tab, die ebenfalls Steuerzeichen sind). Ein weiteres Beispiel für Steuerzeichen im Terminal, die beim Kopieren normalerweise ignoriert werden, sind Farbcodes, also ein ESCZeichen gefolgt vom Code zum Einfärben des Textes.

Um die Zeichen auf Ihrem Terminal anzuzeigen, gibt es keine andere Möglichkeit, als ein Programm zu verwenden, das das Einheitentrennzeichen durch ein druckbares Zeichen ersetzt.

Antwort3

Ein wenig am Rande der anderen (sehr guten) Antworten, wenn Sie ändern möchtennurdas Steuerzeichen ^_bei der Anzeige des Dateiinhalts, möchten Sie möglicherweisetransliterierenes mit dem trDienstprogramm (und ein wenig Bash-kompatibler Syntax):

# Replace the control character US (^_) by *one* other character
$ cat my.file | tr $'\c_' ':'

Wenn Sie dieses Steuerzeichen durch seine „erweiterte“ Form ersetzen müssen, benötigen Sie sedstattdessen:

# Replace the control character US (^_) by any string
cat /tmp/f | sed s/$'\c_'/^_/g

Bitte beachten Sie die Syntax $'\cX': Diese Syntax weist Ihre (bash-kompatible Shell) an, das entsprechende Steuerzeichen zu ersetzen. SieheWikipedia für eine Liste von Steuerzeichen-Aliasenmit der „Caret-Notation“. Wenn Ihnen diese Syntax nicht gefällt, können Sie stattdessen auch die Oktal- $'\037'oder Hexadezimalnotation verwenden $'\x1f'.

verwandte Informationen