Pourquoi certains caractères Unicode ne s'impriment-ils pas sur mon terminal?


16

J'utilise Arch Linux avec un terminal simple en utilisant la police Adobe Source Code Pro. Mes paramètres régionaux sont correctement définis sur LANG=en_US.UTF-8.

Je souhaite imprimer des caractères Unicode représentant des cartes à jouer sur mon terminal. J'utilise Wikipedia pour référence .

Les caractères Unicode pour les combinaisons de cartes fonctionnent bien. Par exemple, l'émission

$ printf "\u2660"

imprime un cœur noir à l'écran.

Cependant, j'ai des problèmes avec des cartes à jouer spécifiques. Délivrance

$ printf "\u1F0A1"

imprime le symbole Ἂ1au lieu de l'as de pique 🂡. Qu'est-ce qui ne va pas?

Ce problème persiste sur plusieurs terminaux (urxvt, xterm, termite) et toutes les polices que j'ai essayées (DejaVu, Inconsolata).


Avertissement: si cela est géré par printf, il s'agit d'une amélioration non standard. Ne vous attendez donc pas à ce que de telles évasions fonctionnent. Voir: pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
schily

Réponses:


27

help printfdiffère printf(1)pour les séquences d'échappement interprétées, et les documents pour GNU printf disent:

printfinterprète deux syntaxes de caractères introduites dans ISO C 99: \upour les caractères Unicode 16 bits (ISO / IEC 10646), spécifiés comme quatre chiffres hexadécimaux hhhh , et \Upour les caractères Unicode 32 bits, spécifiés comme huit chiffres hexadécimaux hhhhhhhhh . printfrenvoie les caractères Unicode en fonction des LC_CTYPEparamètres régionaux. Les caractères Unicode dans les plages U + 0000… U + 009F, U + D800… U + DFFF ne peuvent pas être spécifiés par cette syntaxe, sauf pour U + 0024 ($), U + 0040 (@) et U + 0060 (`) .

Quelque chose de similaire est spécifié dans le manuel Bash pour ANSI C Quoting et echo:

\uHHHH
le caractère Unicode (ISO / IEC 10646) dont la valeur est la valeur hexadécimale HHHH (un à quatre chiffres hexadécimaux)

\UHHHHHHHH
le caractère Unicode (ISO / IEC 10646) dont la valeur est la valeur hexadécimale HHHHHHHH (un à huit chiffres hexadécimaux)

En bref: \un'est pas pour 5 chiffres hexadécimaux. C'est \U:

# printf "\u2660 \u1F0A1 \U1F0A1\n"
 1 🂡

2

La réponse de Muru est complètement correcte, mais juste pour clarifier un point:

Lorsque vous imprimez \u1F0A1, cela est interprété comme un échappement Unicode de seize bits \u1F0A, suivi du caractère littéral 1(puisqu'il \uprend les quatre caractères suivants, ni plus, ni moins). U + 1F0A donne alors , un alpha grec avec deux diacritiques dessus ( lettre majuscule grecque Alpha avec Psili et Varia , pour être précis).

Si vous voulez plus de seize bits dans votre échappement Unicode, vous devez utiliser \U, ce qui prend la valeur de hex de huit caractères: \U0001F0A1vous donnera la carte à jouer.


\U0001F0A1est en fait plus portable que \U1F0A1. C'est l' printfutilitaire GNU autonome qui a introduit ces séquences \uXXXX/ \UXXXXXXXXet il nécessite 4 chiffres pour \uet 8 pour \U. D'autres printfimplémentations comme le shell intégré GNU, ksh93 et ​​zsh sont plus laxistes. En tout cas ce printf '\u/\U'n'est pas POSIX. POSIX va cependant spécifier des zsh $'\U1F0A1'et ne nécessitera pas les 8 chiffres.
Stéphane Chazelas

@ StéphaneChazelas Intéressant, j'avais toujours pensé que POSIX irait avec celui à huit chiffres. Je suppose que la version à huit chiffres est toujours valide en zsh si vous voulez éviter de capturer des lettres et des chiffres supplémentaires après le code?
Draconis

Oui, \uxxxxest jusqu'à 4 chiffres et \Uxxxxxxxxest jusqu'à 8 chiffres. Notez que Unicode est désormais limité aux points de code 0 à 0x10FFFF (une limitation apportée par UTF16), de sorte que les points de code n'auront jamais plus de 6 chiffres (toujours \U123456789serait interprété comme le caractère du point de code 0x12345678 suivi 9et échoué). La spécification POSIX pour $'\u\U'n'est toujours pas finalisée (voir austingroupbugs.net/view.php?id=249 ). Dans une version antérieure, ils exigeaient tous les 4/8 chiffres, mais cela a changé plus tard (à ma demande).
Stéphane Chazelas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.