Como apagar símbolos unicode no terminal?

3

Alguns símbolos ocupam duas células de caracteres. Considere este script:

#!/usr/bin/env bash
echo '银^Htest'
echo 'а^Htest'

Saída:

 test
test

Como eu sei seus pontos de código de símbolos fullwidth? Algum tipo de regex para isso? Como faço para contar quantas células de caracteres uma string leva? Como apago tudo o que foi enviado?

Estou usando xterm se isso for importante.

UPD Para dar uma visão geral, estou tentando exibir o progresso, gerando algumas informações, apagando-as, exibindo novamente ... Para isso, eu estava movendo o cursor para o início do processo. line ( \r ), apagando a linha com espaços ( tput cols ) e movendo o cursor novamente ( \r ). Mas acabou que a saída pode abranger várias linhas. Então, decidi contar os caracteres, voltar atrás ( ^H ), apagar (espaço de saída quantas vezes o tamanho da string for) e voltar novamente ( ^H ).

    
por x-yuri 28.01.2016 / 14:06

1 resposta

2

Na verdade, são quatro perguntas:

  1. Como conheço seus pontos de código?
  2. Algum tipo de regex?
  3. Como faço para contar quantas células de caracteres uma string leva?
  4. Como apago tudo o que foi enviado?

OP menciona o xterm, mas apenas os dois últimos são possivelmente específicos do xterm.

Para (1) e (2), o comando echo não ajuda muito. É melhor você usar printf , que reconhece escapes de barra invertida. Em algumas implementações (por exemplo, GNU coreutils ), que inclui constantes Unicode, por exemplo,

printf '\u94f6\btest'

embora para expressões regulares , você está novamente melhor usando uma linguagem de script como o Perl (que pode manipular o UTF-8).

Leitura adicional:

As perguntas (3) e (4) são mais interessantes. Primeiro, o script não pode realmente informar quantas células de caracteres uma string recebe antecipadamente, mas pode apenas medi-las após o fato. Isso porque a largura é baseada em uma combinação de comportamento do terminal e do kernel.

  • O xterm usa wcwidth para decidir a largura do personagem, com algumas questões sobre " fontes largas "(largura dupla) e implementações de wcwidth refletindo os vieses do desenvolvedor em relação aos valores Unicode de largura ambígua. O xterm pode ser configurado (em tempo de execução) para usar sua cópia da implementação de wcwidth ; você é avisado de que pode não estar completo nem corresponder às informações reais do código de idioma do sistema.
  • quando o xterm é instruído a apagar parte de um caractere de largura dupla (como no exemplo dado), ele substitui a outra parte por um espaço. A maioria dos outros terminais que imitam o xterm faz isso (embora, em uma rápida verificação, eu notei um simplesmente movendo o cursor, fazendo com que o caractere largo e o texto ASCII se sobreponham). Se você sabia que o valor era de largura dupla, você poderia simplesmente ajustar sua noção de onde o cursor estava.
  • o kernel do Linux não sabe nada sobre wcwidth . Sistemas baseados em Linux desde 2004 têm um recurso em stty chamado iutf8 :

which tells the kernel that input is encoded in UTF-8, for proper editing support in canonical input mode

  • o recurso kernel do Linux é útil para editar entrada , porque ajuda o driver do terminal a fazer algo razoável quando um backspace exclui o caractere anterior. No entanto, não há recurso comparável para saída .

Você pode , como sugerido, usar o relatório de posição do cursor (uma sequência de escape) para encontrar a posição do cursor em pontos diferentes. Mas se você for usar isso para decidir como limpar a linha, pode parecer mais direto apenas mover para a posição antes de imprimir o valor Unicode e começar a limpar a partir desse ponto.

Como alternativa, você poderia dizer ao terminal para salvar a posição do cursor antes de imprimir o caractere largo e restaurá-lo (retroceder). Isso pode parecer mais limpo e mais previsível. Depois de restaurar a posição do cursor, você pode limpar a linha. Todos os três poderiam ser feitos usando sequências de escape - ou tput :

tput sc
printf '\u94f6'
tput rc
tput el
printf 'test'

Além de uma demonstração, isso tem a desvantagem de que o terminal teria apenas uma posição salva para o cursor, e que, para garantir a limpeza de um caractere de largura única / dupla, está desmarcando uma linha inteira. Mas o cursor acabaria no lugar "certo".

por 29.01.2016 / 00:50