Come fai eco a un carattere Unicode a 4 cifre in Bash?
-
03-07-2019 - |
Domanda
Vorrei aggiungere il teschio e le tibie incrociate Unicode al mio prompt della shell (in particolare "SKULL AND CROSSBONES" (U + 2620)), ma non riesco a capire l'incantesimo magico per far risuonare l'eco, o qualsiasi altro carattere Unicode a 4 cifre. Uno a due cifre è facile. Ad esempio, echo -e " \ x55 " ;,.
Oltre alle risposte che seguono, va notato che, ovviamente, il tuo terminale deve supportare Unicode affinché l'output sia quello che ti aspetti. gnome-terminal fa un buon lavoro, ma non è necessariamente attivato di default.
Sull'app Terminale di macOS Vai a Preferenze- > Codifiche e scegli Unicode (UTF-8).
Soluzione
In UTF-8 sono in realtà 6 cifre (o 3 byte).
$ printf '\xE2\x98\xA0'
☠
Per verificare come è codificato dalla console, utilizzare hexdump:
$ printf ☠ | hexdump
0000000 98e2 00a0
0000003
Altri suggerimenti
% echo -e '\u2620' # \u takes four hexadecimal digits
☠
% echo -e '\U0001f602' # \U takes eight hexadecimal digits
😂
Funziona in Zsh (ho verificato la versione 4.3) e in Bash 4.2 o versioni successive.
Finché i tuoi editor di testo possono far fronte a Unicode (presumibilmente codificato in UTF-8) puoi inserire direttamente il punto di codice Unicode.
Ad esempio, nell'editor di testo Vim si entra nella modalità di inserimento e premi Ctrl + V + U e quindi il numero del punto di codice come numero esadecimale di 4 cifre (pad con zeri se necessario). Quindi digitare Ctrl + V + U 2 6 2 0 . Vedi: Qual è il modo più semplice per inserire caratteri Unicode in un documento?
In un terminale che esegue Bash dovresti digitare CTRL + MAIUSC + U e digitare il punto esadecimale del carattere desiderato . Durante l'inserimento, il cursore dovrebbe mostrare un u
sottolineato. La prima non cifra digitata termina l'input e rende il carattere. Quindi potresti essere in grado di stampare U + 2620 in Bash usando il seguente:
echo CTRL + SHIFT + U 2 6 2 0 INVIO INVIO
(La prima immissione termina l'input Unicode e la seconda esegue il comando echo
.)
Credito: Chiedi a Ubuntu SE
Ecco un'implementazione di Bash completamente interna, senza biforcazione, dimensioni illimitate di caratteri Unicode.
fast_chr() {
local __octal
local __char
printf -v __octal '%03o' $1
printf -v __char \\ Ecco un'implementazione di Bash completamente interna, senza biforcazione, dimensioni illimitate di caratteri Unicode.
─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
L'output è stato:
<*>_octal
REPLY= Ecco un'implementazione di Bash completamente interna, senza biforcazione, dimensioni illimitate di caratteri Unicode.
<*>
L'output è stato:
<*>_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
L'output è stato:
<*>Inserisci " & # 9760; " nel tuo script di shell. Con le impostazioni locali corrette e su una console abilitata per Unicode, verrà stampato correttamente:
$ echo ☠
☠
$
Una brutta soluzione "quot" " sarebbe l'output della sequenza UTF-8, ma ciò dipende anche dalla codifica utilizzata:
$ echo -e '\xE2\x98\xA0'
☠
$
Quick one-liner per convertire i caratteri UTF-8 nel loro formato a 3 byte:
var="$(echo -n '☠' | od -An -tx1)"; printf '\\x%s' ${var^^}; echo
Sto usando questo:
$ echo -e '\u2620'
☠
Questo è abbastanza più semplice che cercare una rappresentazione esadecimale ... Sto usando questo nei miei script di shell. Funziona su gnome-term e urxvt AFAIK.
Potrebbe essere necessario codificare il punto di codice come ottale per consentire una rapida decodifica dell'espansione rapida.
U + 2620 codificato come UTF-8 è E2 98 A0.
Quindi in Bash,
export PS1="\342\230\240"
trasformerà il tuo guscio in teschio e ossa.
Uno di questi tre comandi stamperà il carattere desiderato in una console, a condizione che la console accetti Caratteri UTF-8 (quelli più attuali lo fanno):
echo -e "SKULL AND CROSSBONES (U+2620) \U02620"
echo
Successivamente, è possibile copiare e incollare il glifo (immagine, carattere) effettivo in qualsiasi editor di testo (abilitato UTF-8).
Se devi vedere come tale Unicode Code Point è codificato in UTF-8, usa xxd (visualizzatore esadecimale molto meglio di od):
echo
Oppure, in HEX per evitare errori: 0xE2 0x98 0xA0. Cioè, i valori tra lo spazio (HEX 20) e il Line-Feed (Hex 0A).
Se vuoi fare un tuffo nel convertire i numeri in caratteri: guarda qui !
SKULL AND CROSSBONES (U+2620) \U02620'
printf "%b" "SKULL AND CROSSBONES (U+2620) \U02620\n"
SKULL AND CROSSBONES (U+2620) ☠
Successivamente, è possibile copiare e incollare il glifo (immagine, carattere) effettivo in qualsiasi editor di testo (abilitato UTF-8).
Se devi vedere come tale Unicode Code Point è codificato in UTF-8, usa xxd (visualizzatore esadecimale molto meglio di od):
<*>
Oppure, in HEX per evitare errori: 0xE2 0x98 0xA0. Cioè, i valori tra lo spazio (HEX 20) e il Line-Feed (Hex 0A).
Se vuoi fare un tuffo nel convertire i numeri in caratteri: guarda qui !
(U+2620) \U02620' | xxd
0000000: 2855 2b32 3632 3029 20e2 98a0 0a (U+2620) ....
That means that the UTF8 encoding is: e2 98 a0
Oppure, in HEX per evitare errori: 0xE2 0x98 0xA0. Cioè, i valori tra lo spazio (HEX 20) e il Line-Feed (Hex 0A).
Se vuoi fare un tuffo nel convertire i numeri in caratteri: guarda qui !
SKULL AND CROSSBONES (U+2620) \U02620' printf "%b" "SKULL AND CROSSBONES (U+2620) \U02620\n" SKULL AND CROSSBONES (U+2620) ☠Successivamente, è possibile copiare e incollare il glifo (immagine, carattere) effettivo in qualsiasi editor di testo (abilitato UTF-8).
Se devi vedere come tale Unicode Code Point è codificato in UTF-8, usa xxd (visualizzatore esadecimale molto meglio di od):
<*>Oppure, in HEX per evitare errori: 0xE2 0x98 0xA0. Cioè, i valori tra lo spazio (HEX 20) e il Line-Feed (Hex 0A).
Se vuoi fare un tuffo nel convertire i numeri in caratteri: guarda qui !
In bash per stampare un carattere Unicode per l'output usa \ x, \ u o \ U (primo per esadecimale a 2 cifre, secondo per esadecimale a 4 cifre, terzo per qualsiasi lunghezza)
echo -e '\U1f602'
Voglio assegnarlo a una variabile usando la sintassi $ '...'
x=\U1f602'
echo $x
Il builtin printf
(proprio come il printf
dei coreutils conosce la sequenza di escape \ u
che accetta caratteri Unicode a 4 cifre:
\uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)
Test con Bash 4.2.37 (1):
$ printf '\u2620\n'
☠
Se non ti dispiace un one-liner Perl:
$ perl -CS -E 'say "\x{2620}"'
☠
-CS
abilita la decodifica UTF-8 sull'ingresso e la codifica UTF-8 sull'uscita. -E
valuta l'argomento successivo come Perl, con funzionalità moderne come dire
abilitate. Se non vuoi una nuova riga alla fine, usa print
invece di dire
.
Ci scusiamo per aver rianimato questa vecchia domanda. Ma quando si utilizza bash
esiste un approccio molto semplice per creare punti di codice Unicode da un semplice input ASCII, che persino non effettua il fork :
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; };
Utilizzalo come segue per definire alcuni punti di codice
unicode crossbones 0x2620
echo "$crossbones"
o per scaricare i primi 65536 codici unicode su stdout (impiega meno di 2 secondi sulla mia macchina. Lo spazio aggiuntivo è impedire a determinati caratteri di fluire l'uno nell'altro a causa del carattere monospace della shell):
for a in {0..65535}; do unicodes "$a"; printf ' '; done
o per raccontare una storia del genitore un po 'tipica (questo richiede Unicode 2010):
unicodes 0x1F6BC 32 43 32 0x1F62D 32 32 43 32 0x1F37C 32 61 32 0x263A 32 32 43 32 0x1F4A9 10
Spiegazione:
-
printf '\ UXXXXXXXX'
stampa qualsiasi carattere Unicode -
printf '\\ U% 08x' number
stampa\ UXXXXXXXX
con il numero convertito in esadecimale, questo viene quindi inviato ad un altroprintf
per stampare effettivamente il carattere Unicode -
printf
riconosce ottale (0ott), esadecimale (0xHEX) e decimale (0 o numeri che iniziano da 1 a 9) come numeri, in modo da poter scegliere la rappresentazione più adatta -
printf -v var ..
raccoglie l'output diprintf
in una variabile, senza fork (che velocizza enormemente le cose) -
variabile locale
è lì per non inquinare lo spazio dei nomi globale -
local -n var = other
alias davar
aaltro
, pertanto l'assegnazione avar
modificaaltro . Una parte interessante qui è che var
fa parte dello spazio dei nomi locale, mentrealtro
fa parte dello spazio dei nomi globale.- Si noti che non esiste lo spazio dei nomi
local
oglobal
inbash
. Le variabili sono mantenute nell'ambiente e sono sempre globali. Local rimuove semplicemente il valore corrente e lo ripristina quando la funzione viene lasciata di nuovo. Altre funzioni richiamate dall'interno della funzione conlocal
vedranno ancora " local " valore. Questo è un concetto fondamentalmente diverso rispetto a tutte le normali regole di scoping trovate in altre lingue (e ciò che fabash
è molto potente ma può causare errori se sei un programmatore che non ne è consapevole).
- Si noti che non esiste lo spazio dei nomi
Basato su domande Stack Overflow Taglio Unix, rimuovere il primo token e 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")
L'output è il seguente.
Octal representation is following \0342\0230\0240
☠
Facile con un one-liner Python2 / 3:
$ python -c 'print u"\u2620"' # python2
$ python3 -c 'print(u"\u2620")' # python3
Risultati in:
☠
Ecco un elenco di tutte le emoji unicode disponibili:
https://en.wikipedia.org/wiki/Emoji#Unicode_blocks
Esempio:
echo -e "\U1F304"
🌄
Per ottenere il valore ASCII di questo personaggio usa hexdump
echo -e "🌄" | hexdump -C
00000000 f0 9f 8c 84 0a |.....|
00000005
E quindi usa i valori informati in formato esadecimale
echo -e "\xF0\x9F\x8C\x84\x0A"
🌄
Se è noto il valore esadecimale del carattere unicode
H="2620"
printf "%b" "\u$H"
Se è noto il valore decimale di un carattere unicode
declare -i U=2*4096+6*256+2*16
printf -vH "%x" $U # convert to hex
printf "%b" "\u$H"