Bashで4桁のUnicode文字をどのようにエコーしますか?
-
03-07-2019 - |
質問
Unicodeのスカルとクロスボーンをシェルプロンプト(具体的には「SKULL AND CROSSBONES」(U + 2620))に追加したいのですが、エコースピットを行うための魔法の呪文がわかりません。その他の4桁のUnicode文字。 2桁のものは簡単です。たとえば、echo -e" \ x55&quot ;,。
以下の回答に加えて、当然のことながら、出力が期待どおりになるためには、端末がUnicodeをサポートする必要があることに注意してください。 gnome-terminalはこれをうまくやってくれますが、必ずしもデフォルトでオンになっているとは限りません。
macOSのターミナルアプリで[設定]に移動->エンコードとUnicode(UTF-8)を選択します。
解決
UTF-8では、実際には6桁(または3バイト)です。
$ printf '\xE2\x98\xA0'
☠
コンソールによるエンコード方法を確認するには、hexdumpを使用します。
$ printf ☠ | hexdump
0000000 98e2 00a0
0000003
他のヒント
% echo -e '\u2620' # \u takes four hexadecimal digits
☠
% echo -e '\U0001f602' # \U takes eight hexadecimal digits
😂
これは、Zsh(バージョン4.3をチェックしました)およびBash 4.2以降で動作します。
テキストエディターがUnicode(おそらくUTF-8でエンコードされている)に対応できる限り、Unicodeコードポイントを直接入力できます。
たとえば、 Vim テキストエディターでは挿入モードになります Ctrl + V + U を押してから、コードポイント番号を4桁の16進数として(必要に応じてゼロで埋めます)。したがって、 Ctrl + V + U 2 6 2と入力します 0 。参照:ドキュメントにUnicode文字を挿入する最も簡単な方法は何ですか?
Bashを実行している端末で、 CTRL + SHIFT + U と入力し、目的の文字の16進コードポイントを入力します。入力中、カーソルには下線付きの u
が表示されます。入力した最初の非数字は入力を終了し、文字をレンダリングします。したがって、次を使用してBashでU + 2620を印刷できます。
e c h o CTRL + SHIFT + U 2 6 2 0 ENTER ENTER
(最初の入力はUnicode入力を終了し、2番目の入力は echo
コマンドを実行します。)
クレジット: Ubuntu SEに問い合わせ
これは完全に内部的なBash実装であり、フォークなし、無制限のサイズのUnicode文字です。
fast_chr() {
local __octal
local __char
printf -v __octal '%03o' $1
printf -v __char \\これは完全に内部的なBash実装であり、フォークなし、無制限のサイズのUnicode文字です。
─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
出力:
<*>_octal
REPLY=これは完全に内部的なBash実装であり、フォークなし、無制限のサイズのUnicode文字です。
<*>
出力:
<*>_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
出力:
<*>&quot;&#9760;&quot;シェルスクリプトで。正しいロケールおよびUnicode対応のコンソールでは、問題なく印刷されます。
$ echo ☠
☠
$
見苦しい「回避策」 UTF-8シーケンスを出力することになりますが、使用されるエンコーディングによっても異なります。
$ echo -e '\xE2\x98\xA0'
☠
$
UTF-8文字を3バイト形式に変換するクイックワンライナー:
var="$(echo -n '☠' | od -An -tx1)"; printf '\\x%s' ${var^^}; echo
これを使用しています:
$ echo -e '\u2620'
☠
これは、16進表現を検索するよりもかなり簡単です...シェルスクリプトでこれを使用しています。これはgnome-termおよびurxvt AFAIKで機能します。
プロンプトを正しく展開するには、コードポイントを8進数としてエンコードする必要がある場合があります。
UTF-8としてエンコードされたU + 2620はE2 98 A0です。
Bashでは、
export PS1="\342\230\240"
シェルを頭蓋骨と骨に誘導します。
これらの3つのコマンドはいずれも、コンソールがを受け入れる場合、コンソールに必要な文字を出力します。 UTF-8 文字(最新の文字はそうです):
echo -e "SKULL AND CROSSBONES (U+2620) \U02620"
echo
その後、実際のグリフ(画像、文字)をコピーして、任意の(UTF-8対応)テキストエディターに貼り付けることができます。
このようなUnicodeコードポイントがUTF-8でどのようにエンコードされるかを確認する必要がある場合は、xxd(odよりもはるかに優れた16進ビューア)を使用します。
echo
または、エラーを回避するための16進数:0xE2 0x98 0xA0。つまり、スペース(HEX 20)とラインフィード(Hex 0A)の間の値。
数字から文字への変換について詳しく知りたい場合:こちら!
>SKULL AND CROSSBONES (U+2620) \U02620'
printf "%b" "SKULL AND CROSSBONES (U+2620) \U02620\n"
SKULL AND CROSSBONES (U+2620) ☠
その後、実際のグリフ(画像、文字)をコピーして、任意の(UTF-8対応)テキストエディターに貼り付けることができます。
このようなUnicodeコードポイントがUTF-8でどのようにエンコードされるかを確認する必要がある場合は、xxd(odよりもはるかに優れた16進ビューア)を使用します。
<*>
または、エラーを回避するための16進数:0xE2 0x98 0xA0。つまり、スペース(HEX 20)とラインフィード(Hex 0A)の間の値。
数字から文字への変換について詳しく知りたい場合:こちら!
>(U+2620) \U02620' | xxd
0000000: 2855 2b32 3632 3029 20e2 98a0 0a (U+2620) ....
That means that the UTF8 encoding is: e2 98 a0
または、エラーを回避するための16進数:0xE2 0x98 0xA0。つまり、スペース(HEX 20)とラインフィード(Hex 0A)の間の値。
数字から文字への変換について詳しく知りたい場合:こちら!
>SKULL AND CROSSBONES (U+2620) \U02620' printf "%b" "SKULL AND CROSSBONES (U+2620) \U02620\n" SKULL AND CROSSBONES (U+2620) ☠その後、実際のグリフ(画像、文字)をコピーして、任意の(UTF-8対応)テキストエディターに貼り付けることができます。
このようなUnicodeコードポイントがUTF-8でどのようにエンコードされるかを確認する必要がある場合は、xxd(odよりもはるかに優れた16進ビューア)を使用します。
<*>または、エラーを回避するための16進数:0xE2 0x98 0xA0。つまり、スペース(HEX 20)とラインフィード(Hex 0A)の間の値。
数字から文字への変換について詳しく知りたい場合:こちら!
>出力にUnicode文字を出力するbashでは、\ x、\ uまたは\ Uを使用します(最初は2桁の16進数、2番目は4桁の16進数、3番目は任意の長さ)
echo -e '\U1f602'
$ '...'構文を使用して変数に割り当てたい
x=\U1f602'
echo $x
printf
ビルトイン(coreutilsの printf
と同様)は、4桁のUnicode文字を受け入れる \ u
エスケープシーケンスを認識しています:
\uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)
Bash 4.2.37(1)でテスト:
$ printf '\u2620\n'
☠
Perlのワンライナーを気にしない場合:
$ perl -CS -E 'say "\x{2620}"'
☠
-CS
は、入力でUTF-8デコードを有効にし、出力でUTF-8エンコードを有効にします。 -E
は、次の引数をPerlとして評価し、 say
などの最新の機能を有効にします。最後に改行が必要ない場合は、 say
の代わりに print
を使用します。
この古い質問を復活させてすみません。しかし、 bash
を使用する場合、プレーンなASCII入力からUnicodeコードポイントを作成する非常に簡単なアプローチがあります。
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; };
特定のコードポイントを定義するには、次のように使用します
unicode crossbones 0x2620
echo "$crossbones"
または最初の65536個のUnicodeコードポイントをstdoutにダンプします(私のマシンでは2秒未満かかります。追加のスペースは、シェルの等幅フォントのために特定の文字が互いに流れないようにするためです):
for a in {0..65535}; do unicodes "$a"; printf ' '; done
または非常に典型的な親の話をする(これにはUnicode 2010が必要です):
unicodes 0x1F6BC 32 43 32 0x1F62D 32 32 43 32 0x1F37C 32 61 32 0x263A 32 32 43 32 0x1F4A9 10
説明:
-
printf '\ UXXXXXXXX'
はすべてのUnicode文字を出力します -
printf '\\ U%08x' number
は、16進数に変換された数値で\ UXXXXXXXX
を印刷し、これが別のprintf
に送られますUnicode文字を実際に印刷するには -
printf
は、8進数(0oct)、16進数(0xHEX)、および10進数(0または1〜9で始まる数字)を数字として認識するため、最適な表現を選択できます -
printf -v var ..
は、printf
の出力を forkなしで(変数を大幅に高速化する)変数に収集します -
ローカル変数
は、グローバル名前空間を汚染しないためにあります -
local -n var = other
はvar
をother
にエイリアスし、var
への割り当てによりvar >その他
。ここで興味深いのは、var
がローカルネームスペースの一部であり、other
がグローバルネームスペースの一部であるということです。-
bash
にはlocal
またはglobal
名前空間などはありません。変数は環境に保持され、そのような変数は常にグローバルです。ローカルは単に現在の値を片付けて、関数が再び残されたときにそれを復元します。関数内からlocal
で呼び出された他の関数には、引き続き「ローカル」が表示されます。値。これは、他の言語に見られる通常のスコーピングルールとは根本的に異なる概念です(bash
の機能は非常に強力ですが、それを知らないプログラマーの場合はエラーにつながる可能性があります)
-
スタックオーバーフローの質問に基づく Unixの切り取り、最初のトークンの削除 、 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")
出力は次のとおりです。
Octal representation is following \0342\0230\0240
☠
Python2 / 3ワンライナーで簡単:
$ python -c 'print u"\u2620"' # python2
$ python3 -c 'print(u"\u2620")' # python3
結果:
☠
利用可能なすべてのユニコード絵文字のリストは次のとおりです。
https://en.wikipedia.org/wiki/Emoji#Unicode_blocks
例:
echo -e "\U1F304"
🌄
この文字のASCII値を取得するには、hexdumpを使用します
echo -e "🌄" | hexdump -C
00000000 f0 9f 8c 84 0a |.....|
00000005
そして、16進形式で通知された値を使用します
echo -e "\xF0\x9F\x8C\x84\x0A"
🌄
Unicode文字の16進値がわかっている場合
H="2620"
printf "%b" "\u$H"
Unicode文字の10進値がわかっている場合
declare -i U=2*4096+6*256+2*16
printf -vH "%x" $U # convert to hex
printf "%b" "\u$H"