printf e UTF-8 #180
printf e UTF-8 #180
Comments
Uma solução alternativa que funciona para alguns casos, é separar os campos por tabs e usar o expand para trocar os tabs por espaços. Isso é feito na zzestado e funciona no BSD. # trecho no final da zzestado
zzestado --formato '{sigla}\t{nome}\t{capital}\n' | expand -t 6,29 Exemplo de execução: $ zzestado
AC Acre Rio Branco
AL Alagoas Maceió
AP Amapá Macapá
AM Amazonas Manaus
BA Bahia Salvador
CE Ceará Fortaleza
DF Distrito Federal Brasília
ES Espírito Santo Vitória
GO Goiás Goiânia
MA Maranhão São Luís
MT Mato Grosso Cuiabá
MS Mato Grosso do Sul Campo Grande
MG Minas Gerais Belo Horizonte
PA Pará Belém
PB Paraíba João Pessoa
PR Paraná Curitiba
PE Pernambuco Recife
PI Piauí Teresina
RJ Rio de Janeiro Rio de Janeiro
RN Rio Grande do Norte Natal
RS Rio Grande do Sul Porto Alegre
RO Rondônia Porto Velho
RR Roraima Boa Vista
SC Santa Catarina Florianópolis
SP São Paulo São Paulo
SE Sergipe Aracaju
TO Tocantins Palmas
$ |
No BSD, o $ awk 'BEGIN { printf "|%5s|\n", "a" }'
| a|
$ awk 'BEGIN { printf "|%5s|\n", "á" }'
| á|
$ awk 'BEGIN { printf "|%5s|\n", "♥" }'
| ♥|
$ |
No BSD, algumas ferramentas acertam a contagem de caracteres. $ printf "aá♥" | cut -c 2 # cut OK
á
$ printf "aá♥" | cut -c 3
♥
$ printf "aá♥" | wc -c # wc -c NÃO
6
$ printf "aá♥" | wc -m # wc -m OK (mas não sei se -m é portável)
3
$ echo "aá♥" | sed 's/././2' # sed OK
a.♥
$ echo "aá♥" | sed 's/././3'
aá.
$ echo "aá♥" | sed 's/././g'
...
$ |
Dentro do universo ZZ, acredito que a zzpad seja a função ideal para concentrar os esforços de imprimir com o padding correto, incluindo UTF-8. Se conseguirmos arrumá-la, as outras funções que hoje usam Mas tem que arrumar, pois hoje ela sofre do mesmo problema: $ zzpad -l 5 _ a
____a
$ zzpad -l 5 _ á
___á
$ zzpad -l 5 _ ♥
__♥
$ |
Consegui um exemplo funcional em sed: $ echo a | sed -e ':loop' -e 's/^/_/' -e '/^.\{5\}/! b loop'
____a
$ echo á | sed -e ':loop' -e 's/^/_/' -e '/^.\{5\}/! b loop'
____á
$ echo ♥ | sed -e ':loop' -e 's/^/_/' -e '/^.\{5\}/! b loop'
____♥
$ |
A função ainda não consegue passar nestes testes. Vide issue #180
Mais um teste, a contagem de caracteres do bash $ x="aá♥"
$ echo ${#x}
3
$ bash --version
GNU bash, version 3.2.53(1)-release (x86_64-apple-darwin14)
Copyright (C) 2007 Free Software Foundation, Inc.
$ Mas não sei desde qual versão do bash isso funciona. |
Veja issue #180 para mais informações.
@itamarnet desculpe remover o teu awk da $ zzpad -l 5 _ a
____a
$ zzpad -l 5 _ á
____á
$ zzpad -l 5 _ ♥
____♥
$ Agora, a E mais, como ao usar uma subshell a quebra de linha no final é removida, podemos usar esta função diretamente, várias vezes, num único $ echo "$(zzpad -l 5 _ á) $(zzpad -l 5 _ ★)"
____á ____★
$ |
Grande @aureliojargas não precisa se desculpar. |
Com relação ao wc -m, também não sei se é portável, mas parece que sim. Acho que podemos considerar que abrange tudo dentro do universo de ação. Obs.: Pena que "wc -L" tenha uma abrangência menor nos SO's, seria uma mão na roda e economizaria muito código. |
Essa nova versão do zzpad funcionou perfeitamente. |
Infelizmente no GNU Linux o cut não tem a mesma agilidade que no BSD:
O |
Como está o |
Ops.: esqueci de informar. |
Que estranho... As ferramentas GNU em geral são mais avançadas, eram pra suportar melhor o UTF-8. Eu estava tendo problemas também num Debian, até que conferi e o locale não estava definido corretamente em todas as variáveis. Foi só arrumar e daí funcionou. Dá uma olhada como ficou:
Eu estou desconfiado que possa estar faltando alguma coisa no teu locale. |
Pois é Aurélio, deve ser algo que eu ainda não percebi.
Mesmo com LC_ALL=pt_BR.utf8, o problema manteve-se |
É... Está tudo certo com teu locale também. Agora lascou :) Então deve ser isso mesmo. Algumas ferramentas do Linux ainda estão quebradas no UTF-8 e temos que contornar :/ |
A codificação UTF-8 é multibyte, ou seja, cada caractere pode ser composto por um ou mais bytes.
a
é composta por um byteá
é composta por dois bytes♥
é composto por três bytesConfira:
Quando você usa o
printf
para alinhar colunas, definindo uma largura fixa, as coisas não funcionam como se espera, pois oprintf %<número>s
conta bytes e não caracteres:Por isso a saída de algumas funções aparece desalinhada quando há letras acentuadas no resultado. Cada letra acentuada do português vale por dois :/ Exemplos de funções problemáticas:
Talvez no futuro o
printf
seja atualizado para levar em conta a contagem de caracteres e não de bytes, mas como Unicode é um assunto bem complexo, isso pode demorar bastante. Para ter uma ideia do tamanho do problema, veja esta resposta: http://stackoverflow.com/a/9325750/1623438Bem, este é o problema. Abri este issue para discutirmos possíveis soluções. Lembrando que nosso universo se restringe ao português, então uma solução meia-boca somente para caracteres Latin-1 já é suficiente.
printf
?The text was updated successfully, but these errors were encountered: