絵文字はU + xxxxxの形式を使用して指定されているようです
ここで、各xは16進数です。
たとえば、U + 1F615は、「混乱した顔」の 公式のUnicodeコンソーシアムコード です????
私はよく混乱するので、このシンボルには強い親和性があります。
U + 1F615の表現は私にとって混乱を招きます数字には5x4 = 20ビットが必要です。
私はこのシンボルがbashの完全に異なる16進数文字列で表されているように見えることを発見しました:
$echo -n ???? | hexdump
0000000 f0 9f 98 95
0000004
$echo -e "\xf0\x9f\x98\x95"
????
$PS1=$'\xf0\x9f\x98\x95 >'
???? >
U + 1F615が\ x00\x01\xF6\x15。
これら2つのエンコーディングの関係がわかりませんか?
公式のUnicodeコンソーシアムのリスト でシンボルを検索するとき、手間のかかる方法で手動で変換することなく、そのコードを直接使用できるようにしたいと思います。つまり.
この20ビットコードを使用して、32ビットコードを特定できますか?
これら2つの数値の間に関係はありますか?
UTF-8
は、Unicodeの可変長encodingです。 ASCIIのスーパーセットになるように設計されています。エンコーディングの詳細については Wikipedia を参照してください。 \x00 \x01 \xF6 \x15
は、UCS-4BE
またはUTF-32BE
エンコーディングになります。
UnicodeコードポイントからUTF-8エンコーディングを取得するには、ロケールのcharmapがUTF-8(locale charmap
の出力を参照)であると想定すると、次のようになります。
$ printf '\U1F615\n'
????
$ echo -e '\U1F615'
????
$ confused_face=$'\U1F615'
AFAIK、その構文は2000年にスタンドアロンGNU printf
ユーティリティ(GNU Shell)のprintf
ユーティリティではなく)によって導入され、echo
になりました/ printf
/$'...'
builtins first by zsh
in 20 、ksh93 in 2004、bash in 2010(ただし 2014年まで適切に機能しない )ですが、明らかに刺激を受けました他の言語で。
ksh93
は、printf '\x1f615\n'
およびprintf '\u{1f615}\n'
としてもサポートしています。
$'\uXXXX'
および$'\UXXXXXXXX'
は、zsh
、bash
、ksh93
、mksh
およびFreeBSD sh
、GNU printf
、GNU = echo
。
すべての桁が必要なものもあります(\U0001F615
ではなく\U1F615
のように)。ただし、POSIXではより少ない桁数が許可されるため、将来のバージョンで変更される可能性があります。いずれの場合でも、\UXXXXXXXX
が\U0001F615FOX
であったため、\U1F615FOX
の後に$'\U001F615F'OX
のように16進数字が続く場合は、すべての数字が必要です。
文字列の解析時または文字列の展開時に現在のロケールのエンコーディングの文字に展開されるものもあれば、ロケールに関係なくUTF-8でのみ展開されるものもあります。文字が現在のロケールのエンコーディングで使用できない場合、動作はシェルによって異なります。
したがって、移植性を最大限に高めるには、UTF-8ロケールでのみ使用し、すべての数字を使用し、$'...'
で使用するのが最適です。
printf '%s\n' $'\U0001F615'
ご了承ください:
LC_ALL=C.UTF-8; printf '%s\n' $'\U0001F615'
または:
{
LC_ALL=C.UTF-8
printf '%s\n' $'\U0001F615'
}
$'\U0001F615'
が割り当てられる前にLC_ALL
が解析されるため、すべてのシェル(bash
を含む)では機能しません。 (また、システムがC.UTF-8
と呼ばれるロケールを持つことは保証されないことにも注意してください)
あなたは必要になるでしょう:
LC_ALL=C.UTF-8; eval "confused_face=$'\U0001F615'"
または:
LC_ALL=C.UTF-8
printf '%s\n' $'\U0001F615'
(複合コマンドまたは関数内ではありません)。
逆の場合は、UTF-8エンコーディングからUnicodeコードポイントに変換するために、 この他の質問 または その1つ を参照してください。
$ unicode ????
U+1F615 CONFUSED FACE
UTF-8: f0 9f 98 95 UTF-16BE: d83dde15 Decimal: 😕
????
Category: So (Symbol, Other)
Bidi: ON (Other Neutrals)
$ Perl -CA -le 'printf "%x\n", ord shift' ????
1f615
UTF-32(ビッグエンディアン)からUTF-8に変換する方法を次に示します
$ confused=$(echo -ne "\x0\x01\xF6\x15" | iconv -f UTF-32BE -t UTF-8)
$ echo $confused
????
16進数値0x01F615
があり、先頭に0を追加して32ビットを埋めています。
TF-8 のWikipediaページは、UnicodeコードポイントからそのUTF-8表現への変換を非常に明確に説明しています。しかし、シェルスクリプトでそれを自分でやろうとするのは、最善の考えではないかもしれません。
TF-32 は固定幅であり、コードポイントとUTF-32表現の間の対応は簡単です-値は同じです。
頭の中や紙の上でそれを行うための良い方法:
それが何バイトになるかを考えてください:U + 0080の下の値は1バイト、それ以外の場合U + 0800は2バイト、それ以外の場合はU + 10000は3バイト、それ以外は4バイトです。あなたの場合、4バイト。
16進数を8進数に変換します:0373025
。
最後から始めて、一度に2桁の8進数字を剥がして、一連の8進値を取得します:037
030
025
。
予想されるバイト数よりも少ない8進数値がある場合は、先頭に0を追加します:000
037
030
025
。
1つ目以外の場合は、0200
を追加して取得します:000
0237
0230
0225
。
最初に、予想される長さが2の場合は0300
を追加し、3の場合は0340
を、4の場合は0360
を追加してください:360
0237
0230
0225
。
次に、8進エスケープの文字列として書き込みます:\360\237\230\225
。必要に応じて、オプションで16進数に戻します。