¿Por qué el separador de unidades (ASCII 31) es invisible en la salida del terminal?

¿Por qué el separador de unidades (ASCII 31) es invisible en la salida del terminal?

El carácter ASCII separador de unidades (ASCII 31, octal 37) es visible en Vim como un archivo ^_. Pero si imprimo el mismo archivo en la terminal, el carácter es invisible. Esto hace que los campos de una línea se queden pegados:

# 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

Supongo que puedo hacer visible el separador de unidades con cat -v:

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

Pero esto es bastante engorroso. ¿Por qué el separador de unidades no tiene una representación visible cuando se imprime en la salida estándar en el shell Bash? Ni siquiera puedo copiar y pegar correctamente la salida del shell; el separador de unidades se pierde en el proceso.

Respuesta1

El carácter separador de unidades ( US), también conocido como IS1, está en la cntrlclase de caracteres y esnoen la printclase de personaje. Es un carácter de control destinado a organizar el texto en grupos,para programas que están diseñados para hacer uso de esa información. En general, los caracteres no imprimibles probablemente se interpretarán y representarán de manera diferente en diferentes programas o entornos.

La razón por la que lo ve representado como ^_en Vim es porque Vim es un editor interactivo. Puede representar libremente caracteres no imprimibles como quiera, siempre que se escriba en el disco el carácter binario correcto.

No se puede obtener el mismo comportamiento en el shell porque los programas de shell de Unix están escritos para operar y pasarse texto sin formato entre sí. Cuando crea catun archivo, el texto que se escribe en la terminal debe ser el que realmente está en el archivo.

Eso deja que sea el dispositivo terminal el que interprete el carácter. Y resulta que algunos emuladores de terminalhacerrepresentar al USpersonaje de manera diferente a los demás. En gnome-terminal(o cualquier vteterminal basada en), el carácter se representará como un cuadro que contiene el código hexadecimal 001F. En xtermo rxvt, el personaje es efectivamente invisible.

Respuesta2

El separador de unidades está en el rango ASCII dePersonajes de controly por lo tanto no tiene (o normalmente no debería) tener una representación visual.

Vim y algunos otros editores los muestran para que puedas editarlos. Como habrás notado, cat -vtambién lo muestra. La página de manual muestra, que -ves la forma abreviada de --show-nonprinting, lo que hace que reemplace los caracteres que no se imprimen con una representación imprimible, que no es el contenido original del archivo y, por lo tanto, podría causar problemas, si la salida es en realidad para otro programa. .

La representación que ve ya sugiere que es un carácter de control: un carácter antepuesto a ^es una notación común para Ctrl+ el carácter, que es la combinación de teclas que produce este carácter en una terminal. Ctrl+ _te permitirá ingresar el separador de unidades en vim, por ejemplo. Pero otro editor o algún visor GUI podría mostrar el código hexadecimal, un marcador de posición o algo completamente diferente.

Como su terminal no imprime los caracteres de control, tampoco se copia al seleccionar el texto (los caracteres de espacio en blanco como la nueva línea y la tabulación son una excepción aquí, que también son caracteres de control). Otro ejemplo de caracteres de control en el terminal que se suelen ignorar al copiar son los códigos de color, que son un ESCcarácter seguido del código para colorear el texto.

Así que para mostrar los caracteres en tu terminal no queda otra que utilizar un programa que sustituya el separador de unidades por algún carácter imprimible.

Respuesta3

Un poco al margen de las otras respuestas (muy buenas), si quieres modificarsoloel carácter de control ^_al mostrar el contenido del archivo, es posible que deseetranscribirusando la trutilidad (y un poco de sintaxis compatible con bash):

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

Si necesita reemplazar ese carácter de control por su forma "ampliada", necesitará sed:

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

Tenga en cuenta la sintaxis $'\cX': esta sintaxis le informa a su (shell compatible con bash) que reemplace el carácter de control correspondiente. VerWikipedia para obtener una lista de alias de caracteres de control.utilizando la "notación de intercalación". Si no le gusta esa sintaxis, es posible que prefiera utilizar la notación octal $'\037'o hexadecimal .$'\x1f'

información relacionada