¿Cómo haces eco de un carácter Unicode de 4 dígitos en Bash?
-
03-07-2019 - |
Pregunta
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 CROSSBONES' (U + 2620)), pero no puedo descubrir el encantamiento mágico para hacer que Eco lo escupe, o Cualquier otro carácter Unicode de 4 dígitos. Los de dos dígitos son fáciles. Por ejemplo, echo -e " \ x55 " ;,.
Además de las respuestas a continuación, se debe tener en cuenta que, obviamente, su terminal debe ser compatible con Unicode para que la salida sea lo que usted espera. gnome-terminal hace un buen trabajo de esto, pero no está necesariamente activado de forma predeterminada.
En la aplicación Terminal de macOS Vaya a Preferencias- > Codifique y elija Unicode (UTF-8).
Solución
En UTF-8, en realidad son 6 dígitos (o 3 bytes).
$ printf '\xE2\x98\xA0'
☠
Para verificar cómo está codificado por la consola, use hexdump:
$ printf ☠ | hexdump
0000000 98e2 00a0
0000003
Otros consejos
% echo -e '\u2620' # \u takes four hexadecimal digits
☠
% echo -e '\U0001f602' # \U takes eight hexadecimal digits
😂
Esto funciona en Zsh (he revisado la versión 4.3) y en Bash 4.2 o más reciente.
Mientras sus editores de texto puedan manejar Unicode (probablemente codificado en UTF-8), puede ingresar el punto de código de Unicode directamente.
Por ejemplo, en el editor de texto Vim entrarías en el modo de inserción y presione Ctrl + V + U y luego el número del punto de código como un número hexadecimal de 4 dígitos (rellene con ceros si es necesario). Entonces deberías escribir Ctrl + V + U 2 6 2 0 . Consulte: ¿Cuál es la forma más fácil de insertar caracteres Unicode en un documento?
En una terminal que ejecuta Bash, escribirías CTRL + MAYÚS + U y escribirás el punto de código hexadecimal del carácter que deseas . Durante la entrada, el cursor debe mostrar un u
subrayado. El primer dígito que no escribe se termina la entrada y representa el carácter Por lo tanto, podría imprimir U + 2620 en Bash usando lo siguiente:
echo CTRL + MAYÚS + U 2 6 2 0 ENTERENTER
(La primera entrada finaliza la entrada Unicode y la segunda ejecuta el comando echo
).
Crédito: Ask Ubuntu SE
Aquí hay una implementación de Bash totalmente interna, sin bifurcación, tamaño ilimitado de caracteres Unicode.
fast_chr() {
local __octal
local __char
printf -v __octal '%03o' $1
printf -v __char \\ Aquí hay una implementación de Bash totalmente interna, sin bifurcación, tamaño ilimitado de caracteres Unicode.
─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
La salida fue:
<*>_octal
REPLY= Aquí hay una implementación de Bash totalmente interna, sin bifurcación, tamaño ilimitado de caracteres Unicode.
<*>
La salida fue:
<*>_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:
<*>Sólo pon " ? " en su shell script. En la ubicación correcta y en una consola habilitada para Unicode, se imprimirá bien:
$ echo ☠
☠
$
Un feo " solución temporal " sería dar salida a la secuencia UTF-8, pero eso también depende de la codificación utilizada:
$ echo -e '\xE2\x98\xA0'
☠
$
Una sola línea rápida para convertir caracteres UTF-8 a su formato de 3 bytes:
var="$(echo -n '☠' | od -An -tx1)"; printf '\\x%s' ${var^^}; echo
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.
Es posible que deba 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.
Así que en Bash,
export PS1="\342\230\240"
hará que tu caparazón se convierta en cráneo y huesos.
Cualquiera de estos tres comandos imprimirá el carácter que desea en una consola, siempre que la consola acepte Caracteres UTF-8 (la mayoría de los actuales lo hacen):
echo -e "SKULL AND CROSSBONES (U+2620) \U02620"
echo
Después, puedes 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 dicho Punto de Código Unicode en UTF-8, use xxd (mucho mejor visor hexadecimal que od):
echo
O, en HEX para evitar errores: 0xE2 0x98 0xA0. Es decir, los valores entre el espacio (HEX 20) y el avance de línea (Hex 0A).
Si quieres una inmersión profunda en la conversión de números a caracteres: mira aquí !
SKULL AND CROSSBONES (U+2620) \U02620'
printf "%b" "SKULL AND CROSSBONES (U+2620) \U02620\n"
SKULL AND CROSSBONES (U+2620) ☠
Después, puedes 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 dicho Punto de Código Unicode en UTF-8, use xxd (mucho mejor visor hexadecimal que od):
<*>
O, en HEX para evitar errores: 0xE2 0x98 0xA0. Es decir, los valores entre el espacio (HEX 20) y el avance de línea (Hex 0A).
Si quieres una inmersión profunda en la conversión de números a caracteres: mira aquí !
(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, en HEX para evitar errores: 0xE2 0x98 0xA0. Es decir, los valores entre el espacio (HEX 20) y el avance de línea (Hex 0A).
Si quieres una inmersión profunda en la conversión de números a caracteres: mira aquí !
SKULL AND CROSSBONES (U+2620) \U02620' printf "%b" "SKULL AND CROSSBONES (U+2620) \U02620\n" SKULL AND CROSSBONES (U+2620) ☠Después, puedes 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 dicho Punto de Código Unicode en UTF-8, use xxd (mucho mejor visor hexadecimal que od):
<*>O, en HEX para evitar errores: 0xE2 0x98 0xA0. Es decir, los valores entre el espacio (HEX 20) y el avance de línea (Hex 0A).
Si quieres una inmersión profunda en la conversión de números a caracteres: mira aquí !
En bash para imprimir un carácter Unicode para imprimir use \ x, \ u o \ U (primero para hexadecimal de 2 dígitos, segundo para hexadecimal de 4 dígitos, tercero para cualquier longitud)
echo -e '\U1f602'
Si desea asignarlo a una variable, use la sintaxis de $ '...'
x=\U1f602'
echo $x
El printf
incorporado (así como el printf
de 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'
☠
Si no te importa una línea de Perl:
$ perl -CS -E 'say "\x{2620}"'
☠
-CS
habilita la decodificación de UTF-8 en la entrada y la codificación de UTF-8 en la salida. -E
evalúa el siguiente argumento como Perl, con características modernas como say
habilitado. Si no desea una nueva línea al final, use print
en lugar de say
.
Lo siento por revivir esta vieja pregunta. Pero cuando se utiliza bash
, existe un enfoque muy sencillo para crear puntos de código Unicode a partir de una entrada ASCII simple, que incluso no se bifurca en absoluto:
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; };
Ú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 en la salida estándar (toma menos de 2 segundos en mi máquina. El espacio adicional es para evitar que ciertos caracteres fluyan entre sí debido a la fuente monoespaciado de la shell):
for a in {0..65535}; do unicodes "$a"; printf ' '; done
o para contar un poco la historia típica de los padres (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 carácter Unicode -
printf '\\ U% 08x' número
imprime\ UXXXXXXXX
con el número convertido a Hex, que luego se envía a otraprintf
para imprimir realmente el carácter Unicode -
printf
reconoce octal (0oct), hex (0xHEX) y decimal (0 o números que comienzan con 1 a 9) como números, por lo que puede elegir la representación que mejor se ajuste -
printf -v var ..
reúne la salida deprintf
en una variable, sin bifurcación (lo que acelera enormemente las cosas) -
variable local
está ahí para no contaminar el espacio de nombres global -
local -n var = other
aliasvar
aother
, de modo que la asignación avar
altera aotros
. Una parte interesante aquí es quevar
es parte del espacio de nombres local, mientras queotro
es parte del espacio de nombres global.- Tenga en cuenta que no existe el espacio de nombres
local
oglobal
enbash
. Las variables se mantienen en el medio ambiente, y 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 conlocal
seguirán viendo " local " valor. Este es un concepto fundamentalmente diferente a todas las reglas de alcance normales que se encuentran en otros lenguajes (y lo quebash
hace es muy poderoso, pero puede generar errores si usted es un programador que no está al tanto). / li>
- Tenga en cuenta que no existe el espacio de nombres
Basado en preguntas sobre desbordamiento de pila Corte de Unix, eliminar 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
☠
Fácil con una línea de Python2 / 3:
$ python -c 'print u"\u2620"' # python2
$ python3 -c 'print(u"\u2620")' # python3
Resultados en:
☠
Aquí hay una lista de todos los emojis de Unicode disponibles:
https://en.wikipedia.org/wiki/Emoji#Unicode_blocks
Ejemplo:
echo -e "\U1F304"
🌄
Para obtener el valor ASCII de este carácter, use hexdump
echo -e "🌄" | hexdump -C
00000000 f0 9f 8c 84 0a |.....|
00000005
Y luego use los valores informados en formato hexadecimal
echo -e "\xF0\x9F\x8C\x84\x0A"
🌄
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"