Les jeux de caractères sous Linux

Retour à la page Systèmes

Motivation

Souvent le terminal n'affiche pas les caractères attendus.
Cette page présente quelques recettes (non-exhaustives!) pour traquer la source du problème et tenter d'en isoler les acteurs.
Elle comporte un certain nombre de caractères spéciaux affichables sur tout navigateur internet acceptant l'UTF8 (i.e. tout navigateur récent).

Diagnostic

Une première idée consiste à tester un cas de base avec un minimun d'intervenants:

Si les manipulations précédentes ne résolvent pas le problème, chercher la nature des caractères indésirables:

On peut souvent reconnaître pifométriquement le type de problème (s'affichera bien en UTF-8):

Conversion de caractères

Linux propose la commande «iconv» pour lire des caractères et les convertir d'un jeu de caractères à un autre.

Ainsi, pour afficher un fichier latin-1 dans un terminal UTF-8:

iconv <fichier-lat1 >fichier-utf8         #Conversion de fichier
cat fichier-lat1 | iconv -f ISO-8859-1 -t UTF-8 #Conversion juste pour l'affichage

Comme les «pipes» de Linux transmettent des octets sans interprétation, on peut récupérer leur valeur hexa au besoin.
Ainsi, pour voir le numéro unicode d'un caractère � copié-collé dans un terminal UTF-8:

echo -n � | iconv -f utf-8 -t utf-32be | hexdump -C
00000000  00 00 ff fd                                       |....|

Explication: le echo -n n'ajoute pas de caractère superflu comme un retour à la ligne, le codage utf-32be est pratiquement le numéro unicode du caractère sur 32 bits (le «be» pour «big endian» met les octets par poids décroissant), et le hexdump traduit ces 32 bits en chiffres hexadécimaux: 0xFFFD.

Le codage UTF-8

Le terme UTF-8 revenant souvent à propos des chaînes de caractères, un peu de vulgarisation ne devrait pas faire de mal. Des explications plus poussées sont dans «man utf-8», «man iconv», «man charsets», et «man unicode»:

Le standard UNICODE fixe un numéros pour chaque caractère de chaque langue. Sans imposer de codage particulier, il reprend les 128 numéros ASCII pour être compatible ( beaucoup d'explications sont ici );

Arrive la question du codage: les numéros UNICODE prennent souvent 2 voire 4 octets en binaire; mais utiliser 2 ou 4 octets par caractère dans des langues proches de l'ASCII serait du gaspillage.

D'où l'idée du codage UTF-8 (Unicode Transformation Format): il écrit les numéros ASCII 0-127 sur un seul octet, et les suivants (>=128) à l'aide d'octets de «prolongation». Voici ce qui a été retenu:

Ce codage a été adopté rapidement pour ses bonnes qualités techniques et pratiques, dont en particulier:

L'inconvénient principal est que la longueur d'une chaîne, en caractères, n'est plus synonyme de sa taille en octets: il faut décoder pour la connaître.

Pour aller plus loin

L'article pourrait se prolonger indéfiniment. Quelques guides complémentaires (en anglais):

Dernière modification: 18 février 2017