web-dev-qa-db-fra.com

Comment faire écho à un caractère Unicode à 4 chiffres dans Bash?

J'aimerais ajouter le crâne et les os croisés Unicode à mon invite Shell (plus précisément le "CRÂNE ET LES CROSSBONES" (U + 2620)), mais je ne peux pas comprendre l'incantation magique pour faire écho le cracher, ni aucun autre, Caractère Unicode à 4 chiffres. Les deux chiffres sont faciles. Par exemple, echo -e "\ x55",.

En plus des réponses ci-dessous, il convient de noter que, évidemment, votre terminal doit prendre en charge Unicode pour que la sortie soit celle que vous attendez. gnome-terminal fait du bon travail dans ce domaine, mais il n'est pas nécessairement activé par défaut. 

Sur l'application Terminal de macOS, allez à Préférences-> Codages et choisissez Unicode (UTF-8).

188
masukomi

En UTF-8, il s'agit en fait de 6 chiffres (ou 3 octets).

$ printf '\xE2\x98\xA0'
☠

Pour vérifier comment il est codé par la console, utilisez hexdump:

$ printf ☠ | hexdump
0000000 98e2 00a0                              
0000003
202
vartec
% echo -e '\u2620'     # \u takes four hexadecimal digits
☠
% echo -e '\U0001f602' # \U takes eight hexadecimal digits
????

Cela fonctionne dans Zsh (j'ai vérifié la version 4.3) et dans Bash 4.2 ou plus récent.

78
Juliano

Tant que vos éditeurs de texte peuvent gérer Unicode (probablement encodé en UTF-8), vous pouvez entrer directement le point de code Unicode.

Par exemple, dans l’éditeur de texte Vim , vous passez en mode insertion et appuyez sur Ctrl + V + U et ensuite le numéro de code sous forme de nombre hexadécimal à 4 chiffres (pavé avec zéros si nécessaire). Donc, vous tapez Ctrl + V + U262. Voir: Quel est le moyen le plus simple d'insérer des caractères Unicode dans un document?

Sur un terminal qui exécute Bash, vous devez taper CTRL+SHIFT+U et tapez le code hexadécimal du caractère souhaité. Pendant la saisie, votre curseur doit afficher un usouligné. Le premier chiffre que vous tapez n'est pas terminé, et restitue le caractère. Vous pouvez donc imprimer U + 2620 dans Bash en utilisant les éléments suivants:

echoCTRL+SHIFT+U262ENTERENTER

(La première entrée termine l'entrée Unicode et la seconde exécute la commande echoname__.)

Crédit: Ask Ubuntu SE

66
RobM

Voici une implémentation Bash entièrement interne, pas de forking, taille illimitée des caractères Unicode.

fast_chr() {
    local __octal
    local __char
    printf -v __octal '%03o' $1
    printf -v __char \\$__octal
    REPLY=$__char
}

function unichr {
    local c=$1    # Ordinal of char
    local l=0    # Byte ctr
    local o=63    # Ceiling
    local p=128    # Accum. bits
    local s=''    # Output string

    (( c < 0x80 )) && { fast_chr "$c"; echo -n "$REPLY"; return; }

    while (( c > o )); do
        fast_chr $(( t = 0x80 | c & 0x3f ))
        s="$REPLY$s"
        (( c >>= 6, l++, p += o+1, o>>=1 ))
    done

    fast_chr $(( t = p | c ))
    echo -n "$REPLY$s"
}

## test harness
for (( i=0x2500; i<0x2600; i++ )); do
    unichr $i
done

La sortie était:

─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
31
Orwellophile

Il suffit de mettre "" dans votre script Shell. Dans les paramètres régionaux appropriés et sur une console compatible Unicode, l’impression sera parfaite:

$ echo ☠
☠
$

Une "solution de contournement" moche consisterait à sortir la séquence UTF-8, mais cela dépend aussi du codage utilisé:

$ echo -e '\xE2\x98\xA0'
☠
$
13
Joachim Sauer

Une ligne rapide pour convertir les caractères UTF-8 au format 3 octets:

var="$(echo -n '☠' | od -An -tx1)"; printf '\\x%s' ${var^^}; echo
10
David King

J'utilise ceci:

$ echo -e '\u2620'
☠

C'est plus facile que de chercher une représentation hexadécimale ... J'utilise ceci dans mes scripts Shell. Cela fonctionne sur gnome terme et urxvt autant que je sache.

8
Metal3d

Vous devrez peut-être coder le point de code en tant qu'octal pour que l'extension Invite le décode correctement.

U + 2620 codé en UTF-8 est E2 98 A0.

Donc, dans Bash,

export PS1="\342\230\240"

fera de votre invite Shell dans le crâne et les os.

7
cms

Chacune de ces trois commandes imprimera le caractère souhaité dans une console, à condition que la console accepte les caractères UTF-8 (les plus courants le font):

echo -e "SKULL AND CROSSBONES (U+2620) \U02620"
echo $'SKULL AND CROSSBONES (U+2620) \U02620'
printf "%b" "SKULL AND CROSSBONES (U+2620) \U02620\n"

SKULL AND CROSSBONES (U+2620) ☠

Ensuite, vous pouvez copier et coller le glyphe réel (image, caractère) dans n’importe quel éditeur de texte (compatible UTF-8).

Si vous avez besoin de savoir comment ce point de code Unicode est codé en UTF-8, utilisez xxd (visionneuse hexagonale bien meilleure que celle-ci):

echo $'(U+2620) \U02620' | xxd
0000000: 2855 2b32 3632 3029 20e2 98a0 0a         (U+2620) ....

That means that the UTF8 encoding is: e2 98 a0

Ou, dans HEX pour éviter les erreurs: 0xE2 0x98 0xA0. C'est-à-dire les valeurs entre l'espace (HEX 20) et le saut de ligne (Hex 0A).

Si vous voulez approfondir la conversion des nombres en caractères: regardez ici !

4
user2350426

Si vous n’êtes pas dérangé par le Perl one-liner:

$ Perl -CS -E 'say "\x{2620}"'
☠

-CS permet le décodage UTF-8 en entrée et le codage UTF-8 en sortie. -E évalue le prochain argument en tant que Perl, avec des fonctionnalités modernes telles que say activé. Si vous ne voulez pas de nouvelle ligne à la fin, utilisez print au lieu de say.

3
Flimm

La variable printf (tout comme la variable printf de coreutils) connaît la séquence d'échappement \u qui accepte les caractères Unicode à 4 chiffres:

   \uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)

Test avec Bash 4.2.37 (1):

$ printf '\u2620\n'
☠
3
Michael Jaros

En bash, pour imprimer un caractère Unicode à la sortie, utilisez\x,\u ou\U (premier pour 2 chiffres hexadécimaux, deuxième pour 4 chiffres hexadécimaux, troisième pour toute longueur)

echo -e '\U1f602'

Si vous souhaitez l’affecter à une variable d’utilisation $ '...', la syntaxe

x=$'\U1f602'
echo $x
3
user2622016

Sur la base des questions de débordement de pile Unix coupé, supprimez le premier jeton et https://stackoverflow.com/a/15903654/781312:

(octal=$(echo -n ☠ | od -t o1 | head -1 | cut -d' ' -f2- | sed -e 's#\([0-9]\+\) *#\\0\1#g')
echo Octal representation is following $octal
echo -e "$octal")

La sortie est la suivante.

Octal representation is following \0342\0230\0240
☠
2
test30

Désolé de faire revivre cette vieille question. Mais lorsque vous utilisez bash, il existe une approche très simple pour créer des points de code Unicode à partir d'une entrée simple ASCII, qui même ne divise pas le tout:

unicode() { local -n a="$1"; local c; printf -vc '\\U%08x' "$2"; printf -va "$c"; }
unicodes() { local a c; for a; do printf -vc '\\U%08x' "$a"; printf "$c"; done; };

Utilisez-le comme suit pour définir certains points de code

unicode crossbones 0x2620
echo "$crossbones"

ou vider les premiers points de code 65536 unicode sur stdout (prend moins de 2 sur ma machine. L'espace supplémentaire sert à empêcher certains caractères de s'écouler les uns dans les autres en raison de la police monospace de Shell):

for a in {0..65535}; do unicodes "$a"; printf ' '; done

ou pour raconter l'histoire d'un parent très typique (cela nécessite Unicode 2010):

unicodes 0x1F6BC 32 43 32 0x1F62D 32 32 43 32 0x1F37C 32 61 32 0x263A 32 32 43 32 0x1F4A9 10

Explication:

  • printf '\UXXXXXXXX' imprime n'importe quel caractère Unicode
  • printf '\\U%08x' number imprime \UXXXXXXXX avec le nombre converti en hexadécimal; il est ensuite transmis à une autre printf pour imprimer le caractère Unicode.
  • printf reconnaît octal (0oct), hex (0xHEX) et décimal (0 ou nombres commençant de 1 à 9) en tant que nombres, ce qui vous permet de choisir la représentation qui vous convient le mieux.
  • printf -v var .. rassemble le résultat de printf dans une variable, sans fork (ce qui accélère énormément les choses)
  • local variable est là pour ne pas polluer l'espace de noms global
  • local -n var=other aliases var à other, de sorte que l'attribution à var modifie other. Une partie intéressante ici est que var fait partie de l’espace de noms local, alors que other fait partie de l’espace de noms global .
    • Veuillez noter qu’il n’existe pas de noms de noms local ou global dans bash. Les variables sont conservées dans l'environnement et sont toujours globales. Local met simplement de côté la valeur actuelle et la restaure lorsque la fonction est à nouveau laissée. Les autres fonctions appelées depuis la fonction avec local verront toujours la valeur "locale". Il s’agit d’un concept fondamentalement différent de toutes les règles de portée classiques que l’on trouve dans les autres langues (ce que bash fait est très puissant, mais peut entraîner des erreurs si vous êtes un programmeur qui n’en est pas conscient).
2
Tino

Facile avec un Python2/3 one-liner:

$ python -c 'print u"\u2620"'    # python2
$ python3 -c 'print(u"\u2620")'  # python3

Résulte en:

2
Chris Johnson

Voici une liste de tous les émoticônes Unicode disponibles:

https://en.wikipedia.org/wiki/Emoji#Unicode_blocks

Exemple:

echo -e "\U1F304"
????

Pour obtenir la valeur ASCII de ce caractère, utilisez hexdump

echo -e "????" | hexdump -C

00000000  f0 9f 8c 84 0a                                    |.....|
00000005

Et puis utilisez les valeurs renseignées au format hexadécimal

echo -e "\xF0\x9F\x8C\x84\x0A"
????
0
Matheus Baldasso

Si la valeur hexadécimale du caractère unicode est connue

H="2620"
printf "%b" "\u$H"

Si la valeur décimale d'un caractère unicode est connue

declare -i U=2*4096+6*256+2*16
printf -vH "%x" $U              # convert to hex
printf "%b" "\u$H"
0
philcolbourn