bash - programas - shell script linux español
¿Cómo se hace eco de un carácter Unicode de 4 dígitos en Bash? (15)
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:
─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
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. Vaya a Terminal-> Configurar codificación de caracteres y elija Unicode (UTF-8).
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í !
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''
☠
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
En función de las preguntas sobre el desbordamiento de pila, Unix cortó, eliminó el primer token y https://.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
☠
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.
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 -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 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 otraprintf
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 deprintf
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
aliasvar
aother
, tal que la asignación avar
altera aother
. Una parte interesante aquí es quevar
es parte del espacio de nombres local, mientras que elother
es parte del espacio de nombres global.- Tenga en cuenta que no existe
global
espacio de nombreslocal
oglobal
enbash
. 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 conlocal
aún verán el valor "local". Este es un concepto fundamentalmente diferente de todas las reglas de alcance normal encontradas en otros lenguajes (y lo quebash
hace es muy poderoso pero puede llevar a errores si usted es un programador que no está enterado de eso).
- Tenga en cuenta que no existe
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
Si no te importa un Perl de una sola línea:
$ perl -CS -E ''say "/x{2620}"''
☠
-CS
habilita la decodificación UTF-8 en la entrada y la codificación 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
.
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"
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 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
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 codificación utilizada:
$ echo -e ''/xE2/x98/xA0''
☠
$
% echo -e ''/u2620''
☠
Esto funciona en Zsh (he comprobado la versión 4.3) y en Bash 4.2 o posterior.