O caractere separador de unidade ASCII (ASCII 31, octal 37) é visível no Vim como um arquivo ^_
. Mas se eu imprimir o mesmo arquivo no terminal, o caractere ficará invisível. Isso faz com que os campos de uma linha fiquem presos:
# 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
Suponho que posso tornar o separador de unidades visível com cat -v:
cat -v delim.txt
first field^_second field^_last field
Mas isso é bastante complicado. Por que o separador de unidades não tem uma representação visível quando impresso em stdout no shell Bash? Não consigo nem copiar e colar a saída do shell corretamente; o separador da unidade se perde no processo.
Responder1
O caractere separador de unidades ( US
), também conhecido como IS1
, está na cntrl
classe de caracteres e énãona print
classe de personagem. É um caractere de controle destinado a organizar o texto em grupos,para programas projetados para fazer uso dessas informações. Em geral, os caracteres não imprimíveis provavelmente serão interpretados e renderizados de maneira diferente em diferentes programas ou ambientes.
A razão pela qual você o vê representado como ^_
no Vim é porque o Vim é um editor interativo. Ele pode renderizar livremente caracteres não imprimíveis da maneira que desejar, desde que o caractere binário correto seja gravado no disco.
Você não pode obter o mesmo comportamento no shell porque os programas shell do Unix são escritos para operar e passar texto simples entre si. Quando você cat
cria um arquivo, o texto gravado no terminal deve ser o que realmente está no arquivo.
Então isso deixa para o dispositivo terminal interpretar o personagem. E acontece que alguns emuladores de terminalfazertornar o US
personagem diferente dos outros. Em gnome-terminal
(ou em qualquer vte
terminal baseado em -), o caractere será renderizado como uma caixa contendo o código hexadecimal 001F
. Em xterm
ou rxvt
, o personagem é de fato invisível.
Responder2
O separador de unidades está na faixa ASCII dePersonagens de controlee, portanto, não tem (ou normalmente não deveria) ter uma representação visual.
O Vim e alguns outros editores os exibem, para que você possa editá-los. Como você notou, cat -v
também exibe. A página de manual mostra que essa -v
é a forma abreviada de --show-nonprinting
, o que faz com que ele substitua os caracteres não imprimíveis por uma representação imprimível, que não é o conteúdo original do arquivo e pode, portanto, causar problemas, se a saída for realmente para outro programa .
A representação que você vê já sugere que é um caractere de controle: um caractere prefixado com a ^
é uma notação comum para Ctrl+ o caractere, que é a combinação de teclas que produz esse caractere em um terminal. Ctrl+ _permitirá que você insira o separador de unidades no vim, por exemplo. Mas outro editor ou algum visualizador de GUI pode exibir o código hexadecimal, um espaço reservado ou algo completamente diferente.
Como o seu terminal não imprime os caracteres de controle, ele também não é copiado ao selecionar o texto (os caracteres de espaço em branco como nova linha e tabulação são uma exceção aqui, que também são caracteres de controle). Outro exemplo de caracteres de controle no terminal que geralmente são ignorados na cópia são os códigos de cores, que são um ESC
caractere seguido do código para colorir o texto.
Portanto, para mostrar os caracteres no seu terminal, não há outra maneira senão usar um programa que substitua o separador de unidades por algum caractere imprimível.
Responder3
Um pouco à margem das outras respostas (muito boas), se quiser alterarapenaso caractere de controle ^_
ao exibir o conteúdo do arquivo, você pode querertransliterarusando o tr
utilitário (e um pouco de sintaxe compatível com bash):
# Replace the control character US (^_) by *one* other character
$ cat my.file | tr $'\c_' ':'
Se precisar substituir esse caractere de controle pela sua forma "expandida", você precisará sed
:
# Replace the control character US (^_) by any string
cat /tmp/f | sed s/$'\c_'/^_/g
Observe a sintaxe $'\cX'
: esta sintaxe informa ao seu (shell compatível com bash) para substituir o caractere de controle correspondente. Verwikipedia para obter uma lista de alias de personagens de controleusando a "notação circunflexa". Se você não gosta dessa sintaxe, talvez prefira usar a notação octal $'\037'
ou hexadecimal .$'\x1f'