Perché il separatore unità (ASCII 31) è invisibile nell'uscita del terminale?


17

Il carattere ASCII del separatore unità (ASCII 31, ottale 37), è visibile in Vim come a ^_. Ma se stampo lo stesso file sul terminale, il personaggio è invisibile. Questo fa sì che i campi su una linea rimangano bloccati insieme:

# 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

Suppongo di poter rendere visibile il separatore unità con cat -v:

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

Ma questo è piuttosto ingombrante. Perché il separatore unità non ha una rappresentazione visibile quando viene stampato su stdout nella shell Bash? Non riesco nemmeno a copiare e incollare correttamente l'output della shell; il separatore dell'unità si perde nel processo.


Non tutti i caratteri sono stampabili, il separatore di unità è uno di questi. Alcuni editor lo visualizzeranno in qualche modo per rendere possibile la modifica. È necessario tradurlo in una sequenza di caratteri stampabili e forse in un carattere / colore diverso, per ridurre l'ambiguità.
ctrl-alt-delor

3
I codici ASCII al di sotto di 31 e 127, hanno lo scopo di indurre un terminale o un dispositivo a fare qualcosa (quindi perché sono chiamati codici di controllo), o rappresentare qualcosa in un protocollo (come EOT o SOH), invece di mostrare qualcosa. Si sente quando i terminali erano dispositivi simili a macchine da scrivere e cose come il dire un teletipo al ritorno a capo erano fisicamente necessarie. I redattori possono scegliere di renderli usando la notazione "^" poiché stai modificando qualcosa e non vuoi terminare per fare effettivamente ciò che chiedono i codici di controllo.
LawrenceC,

1
@LawrenceC: il codice 127 in realtà intendeva impedire a un terminale di non fare nulla . Se si stesse perforando un nastro e si commetteva un errore, si premeva un pulsante per eseguire il backup del nastro di uno spazio e si premeva "rub-out", per dare un pugno a tutto otto buche. Quando il lettore incontrava il personaggio perforato, lo inviava sul filo ma il destinatario poteva semplicemente ignorarlo.
supercat,

Risposte:


19

Il carattere separatore unità ( US), noto anche come IS1, è nella cntrlclasse di caratteri e non nella printclasse di caratteri. È un carattere di controllo destinato all'organizzazione del testo in gruppi, per i programmi progettati per utilizzare tali informazioni . In generale, i caratteri non stampabili verranno probabilmente interpretati e resi in modo diverso in diversi programmi o ambienti.

Il motivo per cui lo vedi rappresentato come ^_in Vim è perché Vim è un editor interattivo. Può rendere liberamente i caratteri non stampabili come vuole, purché il carattere binario corretto sia scritto sul disco.

Non è possibile ottenere lo stesso comportamento nella shell perché i programmi della shell Unix sono scritti per funzionare e si scambiano testo in chiaro. Quando si è catun file, il testo che è scritto sul terminale deve essere quello che è effettivamente nel file.

In modo che lascia al dispositivo terminale per interpretare il personaggio. E si scopre che alcuni emulatori di terminale fanno rendere il UScarattere diverso dagli altri. Nel gnome-terminal(o in qualsiasi vteterminale basato su), il carattere verrà visualizzato come una casella contenente il codice esadecimale 001F. In xtermo rxvt, il personaggio è davvero invisibile.


Beh, non direi che USè totalmente invisibile. Quando inserisco quel personaggio in un terminale con Ctrl+/(confermato tramite <C-v><C-/>), cancella una quantità imprevedibile di testo sulla riga. Non capisco appieno il suo comportamento, ma sembra avere principalmente una sorta di effetto di "tabulazione inversa" dove invece di inserire un numero di spazi, cancella un numero di caratteri, ma a volte inserisce casualmente del testo, quindi è confuso .
Braden Best

10

Il separatore di unità si trova nell'intervallo ASCII di caratteri di controllo e pertanto non ha (o non dovrebbe di solito) avere una rappresentazione visiva.

Vim e alcuni altri editor li visualizzano, quindi puoi modificarli. Come hai notato, lo cat -vvisualizza anche. La pagina man mostra, questa -vè la forma abbreviata di --show-nonprinting, che gli fa sostituire i caratteri non stampabili con una rappresentazione stampabile, che non è il contenuto originale del file e potrebbe quindi causare problemi, se l'output è effettivamente su un altro programma .

La rappresentazione che vedi suggerisce già che è un personaggio di controllo: un personaggio anteposto con a ^è una notazione comune per Ctrl+ il personaggio, che è la combinazione chiave che produce questo personaggio in un terminale. Ctrl+ _ti permetterà di inserire il separatore di unità in vim, ad esempio. Ma un altro editor o qualche visualizzatore della GUI potrebbe visualizzare il codice esadecimale, un segnaposto o qualcosa di completamente diverso.

Poiché il terminale non stampa i caratteri di controllo, non viene copiato durante la selezione del testo (i caratteri di spazi bianchi come newline e tab sono un'eccezione qui, che sono anche caratteri di controllo). Un altro esempio di caratteri di controllo nel terminale che di solito vengono ignorati durante la copia sono i codici colore, che sono un ESCcarattere seguito dal codice per colorare il testo.

Quindi, per mostrare i caratteri sul tuo terminale, non c'è altro modo di usare un programma che sostituisca il separatore di unità con un carattere stampabile.


3

Un po 'a margine delle altre (molto buone) risposte, se si desidera modificare solo il carattere di controllo ^_durante la visualizzazione del contenuto del file, è possibile che si desideri traslitterarlo utilizzando l' trutilità (e un po' di sintassi compatibile con bash) :

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

Se devi sostituire quel carattere di controllo con il suo modulo "espanso", dovrai sedinvece:

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

Nota la sintassi $'\cX': questa sintassi informa la tua (shell compatibile con bash) per sostituire il carattere di controllo corrispondente. Vedi Wikipedia per un elenco di alias dei caratteri di controllo usando la "notazione con il cursore". Se non ti piace quella sintassi, potresti preferire invece usare la notazione ottale $'\037'o esadecimale $'\x1f'.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.