Comment faire écho à un caractère Unicode à 4 chiffres dans Bash?
-
03-07-2019 - |
Question
J'aimerais ajouter le crâne et les os croisés Unicode à l'invite de mon shell (plus précisément le "SKULL AND CROSSBONES" (U + 2620)), mais je n'arrive pas à comprendre l'incantation magique pour faire écho le cracher, ou tout 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, de toute évidence, 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, accédez à Préférences- > Encodages et choisissez Unicode (UTF-8).
La solution
En UTF-8, il s’agit 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
Autres conseils
% 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.
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 , puis le numéro du point de code sous la forme d'un nombre hexadécimal à 4 chiffres (pavé avec zéros si nécessaire). Pour taper Ctrl + V + U 2 6 2 0 . Voir: Quel est le moyen le plus simple d'insérer des caractères Unicode dans un document?
Sur un terminal exécutant Bash, vous devez taper CTRL + SHIFT + U et saisir le point de code hexadécimal du caractère souhaité. . Pendant la saisie, votre curseur doit afficher un u
souligné. Le premier chiffre que vous tapez n'est pas terminé, et restitue le caractère. Pour pouvoir imprimer U + 2620 dans Bash, procédez comme suit:
e c h o CTRL + SHIFT + U 2 6 2 0 ENTER ENTER
(La première entrée termine l'entrée Unicode et la seconde exécute la commande echo
.)
Credit: Demander à Ubuntu SE
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 \\ Voici une implémentation Bash entièrement interne, pas de forking, taille illimitée des caractères Unicode.
─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
Le résultat était:
<*>_octal
REPLY= Voici une implémentation Bash entièrement interne, pas de forking, taille illimitée des caractères Unicode.
<*>
Le résultat était:
<*>_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
Le résultat était:
<*>Mettez simplement "" " 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 serait de sortir la séquence UTF-8, mais cela dépend aussi du codage utilisé:
$ echo -e '\xE2\x98\xA0'
☠
$
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
J'utilise ceci:
$ echo -e '\u2620'
☠
C’est plus facile que de chercher dans une représentation hexadécimale ... Je l’utilise dans mes scripts shell. Cela fonctionne sur gnome terme et urxvt autant que je sache.
Vous devrez peut-être coder le point de code en octal pour que le développement rapide puisse le décoder correctement.
U + 2620 codé en UTF-8 est E2 98 A0.
Donc, dans Bash,
export PS1="\342\230\240"
fera en sorte que votre invite soit transformée en crâne et en os.
Chacune de ces trois commandes imprimera le caractère de votre choix dans une console, à condition que la console accepte les Caractères UTF-8 (les plus courants le sont):
echo -e "SKULL AND CROSSBONES (U+2620) \U02620"
echo
Ensuite, vous pouvez copier et coller le glyphe actuel (image, caractère) dans n’importe quel éditeur de texte (UTF-8 activé).
Si vous avez besoin de savoir comment ce point de code Unicode est codé en UTF-8, utilisez xxd (visionneuse hexagonale bien supérieure à celle d'od):
echo
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 souhaitez approfondir la conversion des nombres en caractères: regardez ici !
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 actuel (image, caractère) dans n’importe quel éditeur de texte (UTF-8 activé).
Si vous avez besoin de savoir comment ce point de code Unicode est codé en UTF-8, utilisez xxd (visionneuse hexagonale bien supérieure à celle d'od):
<*>
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 souhaitez approfondir la conversion des nombres en caractères: regardez ici !
(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 souhaitez approfondir la conversion des nombres en caractères: regardez ici !
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 actuel (image, caractère) dans n’importe quel éditeur de texte (UTF-8 activé).
Si vous avez besoin de savoir comment ce point de code Unicode est codé en UTF-8, utilisez xxd (visionneuse hexagonale bien supérieure à celle d'od):
<*>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 souhaitez approfondir la conversion des nombres en caractères: regardez ici !
In bash pour imprimer un caractère Unicode à utiliser, 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'
Je vous souhaitez l'assigner à une variable d'utilisation $ '...' syntaxe
x=\U1f602'
echo $x
Le printf
intégré (tout comme le 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'
☠
Si vous ne craignez pas un Perl one-liner:
$ perl -CS -E 'say "\x{2620}"'
☠
-CS
active 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ée. Si vous ne voulez pas de nouvelle ligne à la fin, utilisez print
au lieu de dites
.
Désolé de faire revivre cette vieille question. Cependant, lorsque vous utilisez bash
, il est très facile de créer des points de code Unicode à partir d'une entrée ASCII simple, ce que même ne divise pas du 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 pour vider les premiers points de code 65536 unicode sur stdout (prend moins de 2 s sur ma machine. L'espace supplémentaire sert à empêcher certains caractères de s'écouler en raison de la police monospace du 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 tout caractère Unicode -
printf '\\ U% 08x' numéro
imprime\ UXXXXXXXX
avec le nombre converti en Hex, il est ensuite envoyé à un autreprintf
pour réellement imprimer le caractère Unicode -
printf
reconnaît octal (0oct), hex (0xHEX) et décimal (0 ou nombres commençant par 1 à 9) sous forme de nombres, ce qui vous permet de choisir la représentation qui convient le mieux -
printf -v var ..
regroupe la sortie deprintf
dans une variable sans fork (qui accélère considérablement les choses) -
variable locale
est là pour ne pas polluer l'espace de noms global -
local -n var = autre
aliasvar
enautre
, de sorte qu'une affectation àvar
modifieautre
. Une partie intéressante ici est quevar
fait partie de l’espace de noms local, tandis queautre
fait partie de l’espace de noms global.- Veuillez noter qu’il n’existe pas d’espace de noms
local
ouglobal
dansbash
. 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 aveclocal
verront toujours le symbole "local". valeur. Ceci est un concept fondamentalement différent de toutes les règles de cadrage normales trouvées dans d'autres langues (et ce quebash
fait est très puissant mais peut entraîner des erreurs si vous êtes un programmeur qui n'en a pas conscience).
- Veuillez noter qu’il n’existe pas d’espace de noms
D'après les questions relatives au débordement de la pile coupe Unix, supprime 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
☠
Facile avec un one-liner Python2 / 3:
$ python -c 'print u"\u2620"' # python2
$ python3 -c 'print(u"\u2620")' # python3
Résultats en:
☠
Voici une liste de tous les emoji 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 utilisez ensuite les valeurs renseignées au format hexadécimal
echo -e "\xF0\x9F\x8C\x84\x0A"
🌄
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"