tr analógico para caracteres unicode?

Necesito una utilidad internacionalizada que haga lo mismo que tr : obtiene el carácter de la secuencia y lo sustituye con un carácter correspondiente. No es una solución de caso particular, como de menor a mayor, pero se necesita una solución de caso general. Sin gorillion llamadas sedimentadas si es posible.

Tenga en count que tr no funciona en Linux: traduce bytes, no caracteres. Esto falla con codificaciones multibyte.

 $ tr --version | head -n 1 tr (GNU coreutils) 8.23 $ echo $LC_CTYPE en_US.UTF-8 $ echo 'Ångstrom' | tr Æ Œ Ņngstrom 

GNU sed funciona con caracteres de varios bytes. Asi que:

 $ echo é½Æ | sed 'y/é½Æ/ABŒ/' ABŒ 

No es tanto que GNU tr no se haya internacionalizado, sino que no admite caracteres de varios bytes (como los que no son ASCII en entornos locales UTF-8). GNU tr funcionaría con Æ , Œ siempre que fueran de un solo byte como en el set de caracteres iso8859-15.

Más sobre eso en ¿Cómo hacer que tr sea consciente de los caracteres no ascii (unicode)?

En cualquier caso, eso no tiene nada que ver con Linux, se trata de la implementación tr en el sistema. Si ese sistema usa Linux como kernel o tr está construido para Linux o usa la API kernel de Linux no es relevante ya que esa parte de la funcionalidad tr tiene lugar en el espacio del usuario.

busybox tr y GNU tr son los más comunes en las distribuciones de software construidas para Linux y no admiten caracteres de varios bytes, pero hay otros que han sido portados a Linux como tr de la inheritance hechizo de herramientas (portado desde OpenSolaris) o de ast-open que hacer.

Tenga en count que sed y y no admite ranges como az . También tenga en count que si esa secuencia de commands que contiene sed 'y/é½Æ/ABŒ/' está escrita en el set de caracteres UTF-8, ya no funcionará como se esperaba si se llama en una configuration regional donde UTF-8 no es el juego de caracteres.

Una alternativa podría ser usar perl :

 perl -Mopen=locale -Mutf8 -pe 'y/a-zé½Æ/A-ZABŒ/' 

Arriba, se espera que el código perl esté en UTF-8, pero procesará la input en la encoding de la localidad (y la salida en esa misma encoding). Si se llama en una configuration regional UTF-8, se transcribirá un UTF-8 Æ (0xc3 0x86) a un UTF-8 Œ (0xc5 0x92) y en un ISO8859-15 igual pero para 0xc6 -> 0xbc.

En la mayoría de las shells, tener esos caracteres UTF-8 dentro de las comillas simples debería estar bien incluso si se llama al script en una configuration regional donde UTF-8 no es el charset (una exception es yash que se quejaría si esos bytes no son válidos personajes en la localidad). Sin embargo, si utiliza otras citas que comillas simples, podría causar problemas. Por ejemplo,

 perl -Mopen=locale -Mutf8 -pe "y/♣\`/&'/" 

fallaría en una configuration regional donde el juego de caracteres es BIG5-HKSCS porque la encoding de \ (0x5c) también está contenida en algunos otros caracteres (como α : 0xa3 0x5c, y la encoding UTF-8 de termina en 0xa3 )

En cualquier caso, no esperes cosas como

 perl -Mopen=locale -Mutf8 -pe 'y/Á-Ź/AZ/' 

para trabajar en eliminar los acentos agudos. Lo anterior es en realidad solo

 perl -Mopen=locale -Mutf8 -pe 'y/\x{c1}-\x{179}/\x{41}-\x{5a}/' 

Es decir, el range se basa en los puntos de código Unicode. Entonces, los ranges no serán útiles fuera de secuencias muy bien definidas que estén en el order " correcto " en Unicode como AZ , 0-9 .

Si desea eliminar los acentos agudos, debe usar herramientas más avanzadas como:

 perl -Mopen=locale -MUnicode::Normalize -pe ' $_ = NFKD($_); s/\x{301}//g; $_ = NFKC($_)' 

Es decir, use formularios de normalización Unicode para descomponer caracteres, eliminar los acentos agudos (aquí la combinación de la forma U+0301 ) y recomponer.

Otra herramienta útil para transliterar Unicode es uconv de ICU . Por ejemplo, lo anterior también se puede escribir como:

 uconv -x '::NFKD; \u0301>; ::NFKC;' 

Aunque solo funcionaría en datos UTF-8. Necesitarías:

 iconv -t utf-8 | uconv -x '::NFKD; \u0301>; ::NFKC;' | iconv -f utf-8 

Para poder procesar datos en la configuration regional del usuario.

En Bash, puede usar la expansión de parameters .

Sustituyendo Å éxito:

 $ string='Hello Ångstrom' $ a='Å' $ b='Œ' $ printf '%s\n' "${string//${a}/${b}}" Hello Œngstrom 

Intentando sustituir Æ , que no es parte de la cadena:

 $ string='Hello Ångstrom' $ a='Æ' $ b='Œ' $ printf '%s\n' "${string//${a}/${b}}" Hello Ångstrom 

Puede ser tu esquema de encoding. Intente ejecutarlo a través de iconv de esta manera:

 echo Ångstrom | iconv -f UTF-8 | tr 'Å' 'Œ' 

Sale con: Œngstrom