web-dev-qa-db-ja.com

Bashで4桁のUnicode文字をどのようにエコーしますか?

シェルプロンプト(具体的には 'SKULL AND CROSSBONES'(U + 2620))にUnicodeスカルとクロスボーンを追加したいのですが、エコースピットなどを行うための魔法の呪文を理解できません。 4桁のUnicode文字。 2桁のものは簡単です。たとえば、echo -e "\ x55"、。

以下の回答に加えて、当然のことながら、出力が期待どおりになるためには、端末がUnicodeをサポートする必要があることに注意してください。 gnome-terminalはこれをうまくやってくれますが、必ずしもデフォルトでオンになっているとは限りません。

MacOSのターミナルアプリで[設定]-> [エンコード]に移動し、Unicode(UTF-8)を選択します。

193
masukomi

UTF-8では、実際には6桁(または3バイト)です。

$ printf '\xE2\x98\xA0'
☠

コンソールによってどのようにエンコードされているかを確認するには、hexdumpを使用します。

$ printf ☠ | hexdump
0000000 98e2 00a0                              
0000003
206
vartec
% echo -e '\u2620'     # \u takes four hexadecimal digits
☠
% echo -e '\U0001f602' # \U takes eight hexadecimal digits
????

これは、Zsh(バージョン4.3を確認しました)およびBash 4.2以降で動作します。

83
Juliano

テキストエディタがUnicode(おそらくUTF-8でエンコードされている)に対応できる限り、Unicodeコードポイントを直接入力できます。

たとえば、 Vim テキストエディターでは、挿入モードに入り、 Ctrl + V + U 次に、4桁の16進数としてのコードポイント番号(必要に応じてゼロを埋め込みます)。だからあなたはタイプする Ctrl + V + U262。参照: ドキュメントにUnicode文字を挿入する最も簡単な方法は何ですか?

Bashを実行しているターミナルで次のように入力します CTRL+SHIFT+U 必要な文字の16進コードポイントを入力します。入力中、カーソルには下線付きのuが表示されます。入力した最初の非数字は入力を終了し、文字をレンダリングします。したがって、次を使用してBashでU + 2620を印刷できます。

echoCTRL+SHIFT+U262ENTERENTER

(最初の入力はUnicode入力を終了し、2番目の入力はechoコマンドを実行します。)

クレジット: buntu SEに尋ねる

66
RobM

これは、完全に内部的なBash実装であり、フォークなし、サイズ制限のない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

出力は:

─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
31
Orwellophile

シェルスクリプトに「☠」を入力するだけです。正しいロケールで、Unicode対応のコンソールでは、問題なく印刷されます。

$ echo ☠
☠
$

い「回避策」はUTF-8シーケンスを出力することですが、それは使用されるエンコーディングにも依存します。

$ echo -e '\xE2\x98\xA0'
☠
$
13
Joachim Sauer

UTF-8文字を3バイト形式に変換するクイックワンライナー:

var="$(echo -n '☠' | od -An -tx1)"; printf '\\x%s' ${var^^}; echo
12
David King

私はこれを使用しています:

$ echo -e '\u2620'
☠

これは、16進数表現を検索するよりもかなり簡単です...私はこれをシェルスクリプトで使用しています。これはgnome-termおよびurxvt AFAIKで機能します。

8
Metal3d

プロンプト展開で正しくデコードするには、コードポイントを8進数としてエンコードする必要がある場合があります。

UTF-8としてエンコードされたU + 2620はE2 98 A0です。

Bashでは、

export PS1="\342\230\240"

シェルプロンプトを頭蓋骨と骨にします。

6
cms

コンソールが TF-8 文字を受け入れている場合(ほとんどの場合はそうです)、これら3つのコマンドのいずれもコンソールに必要な文字を出力します。

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) ☠

その後、実際のグリフ(画像、文字)を任意の(UTF-8対応)テキストエディターにコピーして貼り付けることができます。

そのようなUnicodeコードポイントがUTF-8でどのようにエンコードされているかを確認する必要がある場合は、xxd(odよりもはるかに優れた16進ビューア)を使用します。

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

または、HEXでエラーを回避するために:0xE2 0x98 0xA0。つまり、スペース(HEX 20)とラインフィード(Hex 0A)の間の値。

数値を文字に変換する方法を詳しく知りたい場合: こちらをご覧ください

4
user2350426

Bashでは、Unicode文字を出力するために\ x、\ uまたは\ Uを使用します(最初は2桁の16進数、2番目は4桁の16進数、3番目は任意の長さ)

echo -e '\U1f602'

$ '...'構文を使用して変数に割り当てたい

x=$'\U1f602'
echo $x
4
user2622016

Perlのワンライナーを気にしない場合:

$ Perl -CS -E 'say "\x{2620}"'
☠

-CSは、入力でUTF-8デコードを有効にし、出力でUTF-8エンコードを有効にします。 -Eは、sayなどの最新の機能を有効にして、次の引数をPerlとして評価します。最後に改行が必要ない場合は、printの代わりにsayを使用します。

3
Flimm

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'
☠
3
Michael Jaros

この古い質問を復活させてすみません。しかし、bashを使用する場合、プレーンなASCII入力からUnicodeコードポイントを作成する非常に簡単なアプローチがあります。これは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; };

特定のコードポイントを定義するには、次のように使用します

unicode crossbones 0x2620
echo "$crossbones"

または、最初の65536 Unicodeコードポイントをstdoutにダンプします(私のマシンでは2秒未満かかります。追加のスペースは、Shellの等幅フォントのために特定の文字が互いに流れないようにするためです)。

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 variableは、グローバル名前空間を汚染しないためにあります
  • local -n var=otherは、varへの割り当てがotherを変更するように、varotherにエイリアスします。ここで興味深いのは、varがローカルネームスペースの一部であり、otherがグローバルネームスペースの一部であるということです。
    • localにはglobalbash名前空間などはないことに注意してください。変数は環境に保持され、そのような変数は常にグローバルです。ローカルは単に現在の値を片付けて、関数が再び残されたときにそれを復元します。 localを使用して関数内から呼び出される他の関数は、引き続き「ローカル」値を参照します。これは、他の言語に見られる通常のすべてのスコープ規則とは根本的に異なる概念です(bashが行うことは非常に強力ですが、それを知らないプログラマーの場合はエラーにつながる可能性があります)。
3
Tino

スタックオーバーフローの質問nix cut、remove first tokenおよび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
☠
2
test30

Python2/3ワンライナーで簡単:

$ python -c 'print u"\u2620"'    # python2
$ python3 -c 'print(u"\u2620")'  # python3

結果:

2
Chris Johnson

利用可能なすべてのユニコード絵文字のリストは次のとおりです。

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"
????
1

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"
0
philcolbourn