¿Cómo se hace eco de un carácter Unicode de 4 dígitos en Bash?

Me gustaría agregar el cráneo y las tibias cruzadas de Unicode a mi intérprete de comandos de shell (específicamente el ‘CRÁNEO Y CRUZUELAS’ (U + 2620)), pero no puedo descifrar el hechizo mágico para hacer que el eco lo escupe, o cualquier otro, 4 dígitos del carácter Unicode. Los de dos dígitos son fáciles. Por ejemplo, echo -e “\ x55”,.

Además de las respuestas a continuación, debe tenerse en cuenta que, obviamente, su terminal debe ser compatible con Unicode para que la salida sea la esperada. gnome-terminal hace un buen trabajo al respecto, pero no está necesariamente activado por defecto.

En la aplicación de terminal de macOS Vaya a Preferencias-> Codificaciones y elija Unicode (UTF-8).

En UTF-8, en realidad son 6 dígitos (o 3 bytes).

 $ printf '\xE2\x98\xA0' ☠ 

Para comprobar cómo está codificada por la consola, use hexdump:

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

Esto funciona en Zsh (he comprobado la versión 4.3) y en Bash 4.2 o posterior.

Siempre que sus editores de texto puedan hacer frente a Unicode (supuestamente codificado en UTF-8), puede ingresar directamente el punto de código Unicode.

Por ejemplo, en el editor de texto de Vim debe ingresar el modo de inserción y presionar Ctrl + V + U y luego el número de punto de código como un número hexadecimal de 4 dígitos (pad con ceros si es necesario). Entonces escribirías Ctrl + V + U 2 6 2 0 . Ver: ¿Cuál es la forma más fácil de insertar caracteres Unicode en un documento?

En un terminal ejecutando Bash, debe teclear CTRL + MAYÚS + U y escribir el punto de código hexadecimal del carácter que desea. Durante la entrada, su cursor debe mostrar una u subrayada. El primer tipo que no sea un dígito que escriba finaliza la entrada y representa el carácter. Para que pueda imprimir U + 2620 en Bash usando lo siguiente:

e c h o CTRL + MAYÚS + U 2 6 2 0 ENTER ENTER

(La primera entrada finaliza la entrada Unicode, y la segunda ejecuta el comando echo ).

Crédito: Ask Ubuntu SE

Aquí hay una implementación Bash completamente interna, sin bifurcaciones, tamaño ilimitado de caracteres 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 salida fue:

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

Simplemente ponga “☠” en su script de shell. En la configuración regional correcta y en una consola habilitada para Unicode, se imprimirá correctamente:

 $ echo ☠ ☠ $ 

Una “solución” fea sería generar la secuencia UTF-8, pero eso también depende de la encoding utilizada:

 $ echo -e '\xE2\x98\xA0' ☠ $ 

Quick-liner rápido para convertir caracteres UTF-8 en su formato de 3 bytes:

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

Es posible que necesite codificar el punto de código como octal para que la expansión rápida lo decodifique correctamente.

U + 2620 codificado como UTF-8 es E2 98 A0.

Entonces en Bash,

 export PS1="\342\230\240" 

hará que tu caparazón incite al cráneo y los huesos.

Estoy usando esto:

 $ echo -e '\u2620' ☠ 

Esto es bastante más fácil que buscar una representación hexadecimal … Estoy usando esto en mis scripts de shell. Eso funciona en gnome-term y urxvt AFAIK.

El printf incorporado (igual que el printf coreutils) conoce la secuencia de escape \u , que acepta caracteres Unicode de 4 dígitos:

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

Prueba con Bash 4.2.37 (1):

 $ printf '\u2620\n' ☠ 

Cualquiera de estos tres comandos imprimirá el carácter que desee en una consola, siempre que la consola acepte caracteres UTF-8 (la mayoría de los actuales):

 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) ☠ 

Después, puede copiar y pegar el glifo real (imagen, carácter) en cualquier editor de texto (habilitado para UTF-8).

Si necesita ver cómo se codifica ese punto de código Unicode en UTF-8, use xxd (mucho mejor visor hexadecimal que od):

 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 

O bien, en HEX para evitar errores: 0xE2 0x98 0xA0. Es decir, los valores entre el espacio (HEX 20) y el Line-Feed (Hex 0A).

Si desea profundizar en la conversión de números a caracteres, ¡ mire aquí !

Si no te importa un Perl de una sola línea:

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

-CS habilita la deencoding UTF-8 en la entrada y la encoding UTF-8 en la salida. -E evalúa el siguiente argumento como Perl, con funciones modernas como say habilitado. Si no desea una nueva línea al final, use print lugar de say .

En función de las preguntas sobre el desbordamiento de stack, Unix cortó, eliminó el primer token y 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 salida es la siguiente.

 Octal representation is following \0342\0230\0240 ☠ 

En bash para imprimir un carácter Unicode a la salida utilice \ x, \ u o \ U (primero para hex de 2 dígitos, segundo para hexágono de 4 dígitos, tercero para cualquier longitud)

 echo -e '\U1f602' 

Yo quiero asignarlo a una syntax de uso variable $ ‘…’

 x=$'\U1f602' echo $x 

Fácil a través de Python:

 $ python -c 'print u"\u2620"' 

Resultados en:

  

Perdón por revivir esta vieja pregunta. Pero cuando se usa bash hay un enfoque muy fácil para crear puntos de código Unicode a partir de una entrada ASCII simple, que incluso no se bifurca en absoluto:

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

Úselo de la siguiente manera para definir ciertos puntos de código

 unicode crossbones 0x2620 echo "$crossbones" 

o para volcar los primeros 65536 puntos de código unicode a stdout (toma menos de 2s en mi máquina. El espacio adicional es para evitar que ciertos caracteres fluyan el uno al otro debido a la fuente de monoespacio del shell):

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

o para contar la historia de un padre muy típico (esto necesita Unicode 2010):

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

Explicación:

  • printf '\UXXXXXXXX' imprime cualquier caracter Unicode
  • printf '\\U%08x' number imprime \UXXXXXXXX con el número convertido a Hex, esto luego se carga a otra printf para imprimir el carácter Unicode
  • printf reconoce octal (0oct), hex (0xHEX) y decimal (0 o números que comienzan de 1 a 9) como números, por lo que puede elegir la representación que mejor se adapte
  • printf -v var .. reúne la salida de printf en una variable, sin fork (lo que acelera enormemente las cosas)
  • local variable está allí para no contaminar el espacio de nombres global
  • local -n var=other alias var a other , tal que la asignación a var altera a other . Una parte interesante aquí es que var es parte del espacio de nombres local, mientras que el other es parte del espacio de nombres global.
    • Tenga en cuenta que no existe global espacio de nombres local o global en bash . Las variables se mantienen en el entorno, y tales son siempre globales. Local simplemente guarda el valor actual y lo restaura cuando la función se deja nuevamente. Otras funciones llamadas desde dentro de la función con local aún verán el valor “local”. Este es un concepto fundamentalmente diferente de todas las reglas de scope normal encontradas en otros lenguajes (y lo que bash hace es muy poderoso pero puede llevar a errores si usted es un progtwigdor que no está enterado de eso).

Si se conoce el valor hexadecimal del carácter Unicode

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

Si se conoce el valor decimal de un carácter Unicode

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