$ locale charmap
UTF-8
En mi entorno actual, el conjunto de caracteres es UTF-8, es decir, los caracteres están codificados con 1 a 4 bytes por carácter (aunque debido a que la definición original del código de caracteres permitido UTF-8 apunta hasta 0x7fffffff, la mayoría de las herramientas reconocerían UTF- Secuencias de 8 bytes de hasta 6 bytes).
En ese conjunto de caracteres, todos los caracteres de Unicode están disponibles, a a
se codifica como el valor de byte 65, a 乕
como los 3 bytes 228 185 149 y é
como la secuencia de dos bytes 195 169 por ejemplo.
$ printf 乕 | wc -mc
1 3
$ printf a | wc -mc
1 1
Ahora:
$ export fr_FR.iso885915@euro
$ locale charmap
ISO-8859-15
Modifiqué mi entorno, donde el juego de caracteres ahora es ISO-8859-15 (también se han modificado otras cosas como el idioma, el símbolo de moneda, el formato de fecha, la colección de esas configuraciones regionales se conoce como la configuración regional ). Necesito iniciar un nuevo emulador de terminal en ese entorno para que adapte su representación de caracteres a la nueva configuración regional.
ISO-8859-15 es un conjunto de caracteres de un solo byte, lo que significa que solo tiene 256 caracteres (en realidad, incluso menos de los que están cubiertos). Ese conjunto de caracteres en particular se utiliza para los idiomas de Europa occidental, ya que cubre la mayoría de sus idiomas (y el símbolo del euro).
Tiene el a
carácter con el valor de byte 65 como en UTF-8 o ASCII, también tiene el é
carácter (como se usa comúnmente en francés o español, por ejemplo) pero con el valor de byte 233, no tiene el carácter 乕.
En ese entorno, wc -c
y wc -m
siempre dará el mismo resultado.
En Ubuntu, como en la mayoría de los sistemas modernos similares a Unix, el valor predeterminado suele ser UTF-8, ya que es el único conjunto de caracteres (y codificación) compatible que cubre todo el rango de Unicode.
Existen otras codificaciones de caracteres de varios bytes, pero no son tan compatibles con Ubuntu y tienes que pasar por aros para poder generar una configuración regional con ellas, y si lo haces, encontrarás que muchas cosas no funcionar correctamente.
En efecto, en Ubuntu, los conjuntos de caracteres son de un solo byte o UTF-8.
Ahora, algunas notas más:
En UTF-8, no todas las secuencias de bytes forman caracteres válidos. Por ejemplo, todos los caracteres UTF-8 que no son ASCII se forman con bytes que tienen el conjunto de 8 bits, pero donde solo el primero tiene el conjunto de 7 bits.
Si tiene una secuencia de bytes con el conjunto de 8 bits, ninguno de los cuales tiene el conjunto de 7 bits, entonces eso no se puede traducir a un carácter. Y es entonces cuando comienzas a tener problemas e inconsistencias, ya que el software no sabe qué hacer con ellos. Por ejemplo:
$ printf '\200\200\200' | wc -mc
0 3
$ printf '\200\200\200' | grep -q . || echo no
no
wc
y grep
no encuentra ningún personaje allí sino:
$ x=$'\200\200\200' bash -c 'echo "${#x}"'
3
bash
encuentra 3. Cuando no puede asignar una secuencia de bytes a un carácter, considera cada byte como un carácter.
Puede ser aún más complicado ya que hay puntos de código en Unicode que no son válidos como caracteres, y algunos que no son caracteres , y dependiendo de la herramienta, su codificación UTF-8 puede o no considerarse como un carácter.
Otra cosa a tener en cuenta es la diferencia entre el personaje y el gráfico, y cómo se representan.
$ printf 'e\u301\u20dd\n'
é⃝
$ printf 'e\u301\u20dd' | wc -mc
3 6
Allí, codificamos 3 caracteres como 6 bytes representados como un gráfico, porque tenemos 3 caracteres combinados juntos (un carácter base, un acento agudo combinado y un círculo envolvente combinado).
La implementación de GNU de wc
como se encuentra en Ubuntu tiene un -L
interruptor para indicarle el ancho de visualización de la línea más ancha en la entrada:
$ printf 'e\u301\u20dd\n' | wc -L
1
También encontrarás que algunos personajes ocupan 2 celdas en ese cálculo de ancho como nuestro 乕
personaje de arriba:
$ echo 乕 | wc -L
2
En conclusión: en la palabra más salvaje, byte, carácter y gráfico no son necesariamente lo mismo.