O GNU sed
funciona com caracteres de múltiplos bytes. Então:
$ echo é½Æ | sed 'y/é½Æ/ABŒ/'
ABŒ
Não é tanto que o GNU tr
não tenha sido internacionalizado, mas que ele não suporta caracteres de múltiplos bytes (como os não-ASCII em locais UTF-8). O GNU tr
funcionaria com Æ
, Œ
desde que fossem de byte único, como no conjunto de caracteres iso8859-15.
Mais sobre isso em Como tornar o conhecimento de caracteres não-ascii (unicode)?
Em qualquer caso, isso não tem nada a ver com o Linux, é sobre a implementação tr
no sistema. Se esse sistema usa o Linux como um kernel ou o tr
é construído para o Linux ou usa a API do kernel do Linux, isso não é relevante, já que a parte da funcionalidade tr
ocorre no espaço do usuário.
busybox tr
e GNU tr
são os mais comumente encontrados em distribuições de software criados para Linux e não suportam caracteres de múltiplos bytes, mas há outros que foram portados para o Linux como tr
de o toolchest da herança (portado do OpenSolaris) ou do ast-open que faz.
Observe que sed
do y
não suporta intervalos como a-z
. Observe também que, se esse script que contiver sed 'y/é½Æ/ABŒ/'
for gravado no conjunto de caracteres UTF-8, ele não funcionará mais como esperado se for chamado em uma localidade onde UTF-8 não é o conjunto de caracteres.
Uma alternativa poderia ser usar perl
:
perl -Mopen=locale -Mutf8 -pe 'y/a-zé½Æ/A-ZABŒ/'
Acima, espera-se que o código perl esteja em UTF-8, mas processará a entrada na codificação da localidade (e na mesma codificação). Se chamado em um código do idioma UTF-8, ele transliterará um UTF-8 Æ
(0xc3 0x86) para um UTF-8 Œ
(0xc5 0x92) e em um ISO8859-15, mas para 0xc6 - > 0xbc.
Na maioria dos shells, ter esses caracteres UTF-8 dentro das aspas simples deve ser OK mesmo que o script seja chamado em uma localidade onde UTF-8 não seja o charset (uma exceção é yash
que reclamaria se esses bytes não formam caracteres válidos no idioma). Se você estiver usando outras citações do que aspas simples, isso pode causar problemas. Por exemplo,
perl -Mopen=locale -Mutf8 -pe "y/♣\'/&'/"
falharia em uma localidade onde o conjunto de caracteres é BIG5-HKSCS porque a codificação de \
(0x5c) também está contida em alguns outros caracteres (como α
: 0xa3 0x5c e a codificação UTF-8 de ♣
acaba em 0xa3).
De qualquer forma, não espere coisas como
perl -Mopen=locale -Mutf8 -pe 'y/Á-Ź/A-Z/'
para trabalhar na remoção de acentos agudos. O acima é na verdade apenas
perl -Mopen=locale -Mutf8 -pe 'y/\x{c1}-\x{179}/\x{41}-\x{5a}/'
Ou seja, o intervalo é baseado nos pontos de código unicode. Portanto, os intervalos não serão úteis fora de sequências muito bem definidas que estão na ordem " correto " em Unicode como A-Z
, 0-9
.
Se você quiser remover os acentos agudos, precisará usar ferramentas mais avançadas, como:
perl -Mopen=locale -MUnicode::Normalize -pe '
$_ = NFKD($_); s/\x{301}//g; $_ = NFKC($_)'
Isso é usar formulários de normalização Unicode para decompor caracteres, remover os acentos agudos (aqui o formulário combinando U+0301
) e recompor.
Outra ferramenta útil para transliterar Unicode é uconv
de ICU . Por exemplo, o acima também pode ser escrito como:
uconv -x '::NFKD; \u0301>; ::NFKC;'
Embora funcione apenas em dados UTF-8. Você precisaria:
iconv -t utf-8 | uconv -x '::NFKD; \u0301>; ::NFKC;' | iconv -f utf-8
Para processar dados na localidade do usuário.