8

文字列に「Unicode リテラル」を含めるシェル固有の方法がいくつかあります。たとえば、Bash では、引用符で囲まれた文字列展開メカニズム により$''、目に見えない文字 を直接埋め込むことができます$'\u2620'

ただし、普遍的なクロスプラットフォーム シェル スクリプトを作成しようとしている場合 (通常、これは「Bash、Zsh、および Dash で実行する」ように切り詰めることができます)、それは移植可能な機能ではありません。

次のような構成を使用して、ASCII テーブル (8 進数空間) 内のあらゆるものを移植可能に実現できます。

WHAT_A_CHARACTER="$(printf '\036')"

…しかし、POSIX / Dashprintfは 8 進数のエスケープしかサポートしていません。

また、タスクをより完全なプログラミング環境にファームアウトすることで、明らかに完全な Unicode スペースを実現することもできます。

OH_CAPTAIN_MY_CAPTAIN="$(ruby -e 'print "\u2388"')"
TAKE_ME_OUT_TONIGHT="$(node -e 'console.log("\u266C")')"

したがって、そのような文字をシェルスクリプトにエンコードする最良の方法は何ですか?

  1. dashbash、およびzshで動作します。
  2. コード内のコードポイントの 16 進エンコーディングを示します。
  3. 文字列の特定のエンコーディングに依存していない (つまり、UTF-8 バイトを 8 進数でエンコードしていない)
  4. 最後に、「重い」インタープリターを呼び出す必要はありません。(たとえば、実行時間は 0.01 秒未満です。)
4

2 に答える 2

11

Gnu がインストールされている場合printf(たとえば、 debian パッケージcoreutilsに含まれている場合)、シェルのビルトインを回避することで、使用しているシェルに関係なく使用できます。

env printf '\u2388\n'

ここでは、ビルトインの使用を避けるために Posix 標準envコマンドを使用していprintfますが、たまたま場所がわかっている場合printfは、次のような完全なパスを使用して直接これを行うことができます。

/usr/bin/printf '\u2388\n'

外部printfとシェルのビルトインの両方printfが Posix 標準のみを実装している場合は、さらに努力する必要があります。1 つの可能性はiconvUTF-8 に変換するために を使用することですが、Posix 標準ではコマンドが必要ですが標準iconvエンコーディングの命名方法はまったく規定されていません。以下はほとんどの Posix 互換プラットフォームで機能すると思いますが、作成されるサブシェルの数が多いため、「重い」スクリプト インタープリターよりも効率が低下する可能性があります。

printf $(printf '\\%o' $(printf %08x 0x2388 | sed 's/../0x& /g')) |
iconv -f UTF-32BE -t UTF-8

上記はprintfビルトインを使用して、16 進数のコードポイント値を強制的に 8 桁の 16 進数にし、次にsedそれらを 4 つの 16 進数の定数として書き換え、次にprintf16 進数の定数を 8 進数表記に変更し、最後に別のものを使用printfして 8 進数の文字定数を 4 桁に解釈します。iconvビッグエンディアン UTF-32 として入力できるバイト シーケンス。printf(エスケープコードを認識するa を使用するとより簡単になります\xが、Posix はそれを必要とdashせず、実装していません。)

すべてのシンボルに Unicode コードポイントを (整数定数として) 提供する限り、この行を変更せずに使用して複数のシンボルを出力できます (例は で実行dash)。

$ printf $(printf '\\%o' $(printf %08x 0x2388 0x266c 0xA |
>                          sed 's/../0x& /g')) |
> iconv -f UTF-32BE -t UTF-8
⎈♬
$

: Geoff Nixon がコメントで言及しているように、魚の殻 (これは Posix 標準に近いものではなく、私が見る限り、準拠するという願望はありません) への引用符で囲まれていない%08x形式の引数について不平をprintf言うでしょう。%ジョブスペックになります。したがって、fish を使用する場合は、format 引数に引用符を追加してください。

于 2014-12-26T15:37:41.053 に答える