Em um shell onde \u
é válido (bash +4.3, ksh93 ou zsh), podemos imprimir caracteres Unicode:
$ printf 'a b c \ua0 \ua1 \ua2 \ua3 \n'
a b c ¡ ¢ £
Que são alguns caracteres do intervalo Latin-1_Supplement .
No entanto, assim que um 9f
caractere Unicode é adicionado, a impressão é interrompida até que um Unicode 9c
seja impresso.
Ambos \u9f
e \u9c
(APC e ST) são C1
caracteres de controle .
$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n'
a b c ¡ ¢ £
Os personagens definitivamente desaparecem.
É certo que printf
está gerando todos os caracteres, e que redirecionando a saída para algum outro software (não o terminal) mostrará os caracteres gerados:
$ printf 'a b c \u9f d e f \u9c \ua0 \ua1 \ua2 \ua3 \n' | od -A n -tx1
61 20 62 20 63 20 c2 9f 20 64 20 65 20 66 20 c2
9c 20 c2 a0 20 c2 a1 20 c2 a2 20 c2 a3 20 0a
Isso chega a demonstrar que os personagens estão sendo gerados. Então, por que eles não estão sendo impressos (mostrado com algum glifo visível)?
As perguntas que tenho são:
- Está
APC
realmente conectado aST
. Onde está definido? - Os caracteres entre esses dois caracteres são enviados para algum aplicativo?
- Se sim, para qual aplicação?
- Quem é responsável por tal redirecionamento? O shell, o terminal ou algo mais?
EDITAR
Nem os terminais xterm
nem removem os caracteres.konsole
d e f
Isso confirma que é um problema interno do aplicativo do terminal, não do shell. Ainda não encontrei onde isso está definido.
Esses caracteres de controle não são realmente originais do Unicode, mas herdados de especificações de conjuntos de caracteres mais antigos, como ECMA-48 , ISO/IEC 6429 e a família de codificações de caracteres ISO/IEC-8859. De um modo geral, esses padrões concordam essencialmente uns com os outros nos caracteres de controle C1 (porque eles estão sendo compatíveis com versões anteriores entre si e algumas especificações ainda mais antigas).
Como as cópias da ISO/IEC 6429 estão sendo vendidas, não espero encontrar uma cópia legítima disponível gratuitamente na internet, mas a ECMA-48 diz:
e:
Unicode define apenas um caractere de controle dentro do intervalo de caracteres de controle C1: U+0085 Next Line (NEL). Para quaisquer outros caracteres dentro do intervalo C1, esta parte da especificação se aplica:
Não posso verificá-lo aqui, mas espero que o ISO/IEC 6429 esteja em conformidade com o que o ECMA-48 disse, como acima. Além disso, o autor do terminal pode ter considerado "ser compatível com versões anteriores com codificações de caracteres pré-Unicode de 7 bits e 8 bits, como ECMA-48" para ser um uso específico do aplicativo .
Portanto, o terminal pode interpretar legitimamente os caracteres entre APC e ST como "Não sei para que servem, mas com certeza sei que não devem ser exibidos como saída regular".
O terminal pode ou não estar programado para reagir de alguma forma a algumas strings específicas encapsuladas entre APC e ST e ignorar quaisquer strings não correspondentes. Uma vez que a janela do terminal é o "último passo antes do humano", certamente seria capaz de assumir que qualquer string de comando do programa aplicativo que chega a ela é destinada ao terminal para interpretar e agir, se aplicável, e quaisquer strings irreconhecíveis pelo terminal deve ser erros.
Exibir um caractere de "codificação inválida" ou outra mensagem de erro não seria apropriado, pois a string é codificada de forma válida como "string de controle específica do aplicativo, não para exibição ". Então, a resposta para a pergunta do título "para onde estão indo os personagens?" é mais provável: eles estão sendo descartados como parte de uma string de controle inválida .
Mas observe que a especificação Unicode dizia "... pode ser interpretado...", não "... deve ser interpretado...". Portanto, a escolha das outras implementações de terminal de simplesmente ignorar os caracteres APC e ST como caracteres de controle não imprimíveis sem significado aplicável também não é necessariamente inválida.
Esta questão no Stack Overflow também discute as sequências de controle envolvendo os caracteres de controle APC e ST.
A resposta aceita lá diz:
Os caracteres não estão sendo enviados para nenhum lugar, eles simplesmente não estão sendo exibidos pelo seu terminal apesar de estarem lá na saída:
Você também pode confirmar que eles estão na saída redirecionando para um arquivo e investigando o arquivo:
Parece que o que um terminal faz com a combinação de
\u9f
e\u9c
depende da implementação. Simplesmente acontece que a maneira como seu terminal lida com isso é voltando alguns caracteres e continuando a impressão a partir daí, o que resulta na substituição de outros caracteres. É por isso que você vê:Eu posso reproduzir isso em
gnome-terminator
, masxterm
apenas imprime um espaço:Aqui está a mesma coisa nas capturas de tela:
Isso é semelhante ao que acontece em um caso mais claro, o de usar um retorno de carro (
\r
) cuja função é justamente voltar ao início de uma linha. É por isso que você obtém:O terminal começou a imprimir
12345
, então o\r
enviou de volta para o início da linha onde substituiu o12345
com o67890
então o que você acaba vendo é apenas67890
. Mas o132345
não foi enviado para nenhum outro programa, ainda está lá, simplesmente não é visível porque os outros caracteres o sobrescreveram:Você está explicando comandos que produzem sequências de caracteres UTF8 e os resultados que você vê exibidos na janela do seu emulador de terminal (geralmente chamado de "minha janela de terminal").
Em seguida, você descreve sequências de caracteres que parecem não causar resultados visíveis na janela do emulador de terminal. E você pergunta: "os personagens estão sendo enviados para algum aplicativo?"
Sim, eles estão sendo entregues ao seu emulador de terminal, que interpreta as sequências de caracteres que recebe e decide quais glifos exibirá em sua janela para você visualizar.