Preenchendo strings Unicode com printf do bash
Tentei preencher uma string Unicode com printf do bash e vi isso, enquanto
printf "%2s" a
produz o esperado "a",
uma variante Unicode
printf "%2s" ä
produz um "ä" surpreendentemente não acolchoado. (zsh dá o resultado esperado.)
O que causa isso; e como devo preencher strings Unicode no bash?
Respostas
como devo preencher strings Unicode no bash?
Isso está muito além das capacidades do bash. Se você estiver limitando "strings Unicode" a ascii ++ (sem caracteres de largura dupla, sem bidi, sem marcas de não espaçamento, sem etc.), você pode júri de algo como:
% pad(){ printf '%*s%s\n' "$(($1-${#2}))" "" "$2"; }
% pad 2 €
€
O caractere äé codificado com 2 bytes em UTF-8, então Printf o considera como 2 preenchido.
Podemos contar os caracteres ( -m) e bytes ( -c) de uma string. O número a dar a Printf é então [intended pad]+[bytes]-[chars]. Então eu montei este pad.shscript,
#!/bin/sh
bytes=$(printf '%s' "$2" | wc -c)
chars=$(printf '%s' "$2" | wc -m)
n=$(($1+bytes-chars))
printf "%${n}s" "$2"
No exemplo de execução abaixo, eu adicionei artificialmente novas linhas após cada saída para fins de clareza.
$ sh pad.sh 10 abcdef abcdef $ sh pad.sh 10 äéßôçÈ
äéßôçÈ
bash se comporta corretamente e o programa C
#include <stdio.h>
main()
{
char foo[] = "ä";
printf("%2s\n", foo);
}
se comporta da mesma forma.
Isso ocorre porque% s se refere a uma string orientada a bytes e 'ä' em UTF-8 resulta em 2 bytes.
Pelo que pude testar, nenhum dos outros shells se comporta incorretamente.
O resultado que você espera pode ser visto com algo como:
printf '%2S\n' ä
mas isso não é suportado por nenhum dos shells que testei.