web-dev-qa-db-ja.com

シェルスクリプトでチェック/クロスマークを印刷する

シェルスクリプトでチェックマークとクロスマークを印刷したいと思います。

#!/bin/bash

echo -e "\xE2\x9C\x94 existing"
echo -e "\xE2\x9D\x8C missing"

なぜこれが機能しないのですか?

7
user3142695

コメントでOPによって明らかにされたように、彼らはsh file.shでスクリプトを呼び出していました。 /bin/shがシンボリックリンクされているデフォルトのシェルによっては、Unicode文字をサポートしない場合があります。

たとえば、Ubuntuでは、デフォルトのシェルはdashです。

$ dash
$ printf "\xE2\x9C\x94 missing\n"
\xE2\x9C\x94 missing
$ echo -e "\xE2\x9C\x94"
-e \xE2\x9C\x94

対話型シェルでコマンドを呼び出したときに機能するのは、ユーザー対話型シェルがデフォルトで(Ubuntu)/bin/bashであるためです

スクリプトを適切に実行するには、次のいずれかを行う必要があります。

  • ./file.shとして実行します
  • 適切なシェルbash file.shの引数として実行します

あるいは、シェルに依存しない方法に頼ることもできます:

# this printf is standalone program, not Shell built-in
$ /usr/bin/printf "\xE2\x9C\x94 check mark\n"
✔ check mark

$ python -c 'print "\xE2\x9C\x94 check mark"'
✔ check mark

$ Perl -e 'print "\xE2\x9C\x94 check mark"'                                                                              
✔ check mark
11

\xE2\x9C\x94はU + 2714(重いチェックマーク)文字のUTF-8エンコーディングであることに注意してください。

これらの3バイトは、端末の文字セットがUTF-8である(そしてその文字を持つフォントを使用している)場合にのみチェックマークとして表示されます。

端末エミュレーターの場合、使用する文字セットは通常、起動時のロケールの文字セットになります。そのターミナルで起動したシェル内のロケールを変更していない限り、それがどのロケールであったかを確認できます。

locale charmap

GNU printfおよびprintfprintfzshbashビルトイン(少なくともDebianベースのシステムではlkshのPOSIX互換バリアント)をサポートするいくつかのmksh実装は以下をサポートします:

$ printf '\u2714\u274c\n'
✔❌

これらの文字をロケールの文字セットの正しいエンコーディングで出力するには(ksh93のprintf組み込みは、その\uXXXX表記もサポートしますが、ロケールの文字セットに関係なく常にUTF-8で出力します)。 printfビルトインがそれをサポートし、エスケープシーケンスを拡張するechoを持つシェル(通常は-eを使用)は、通常\uXXXXもサポートします。

現在、AFAICT、これらの2つのU + 274CおよびU + 2714文字が標準的なGNUシステムはUTF-8およびGB18030で使用できる唯一の2つの文字セットです。異なる文字セットを使用するロケールでは、printfはこれらの文字は存在しないため、表示できません。実装によっては、printf\u274Cを文字どおりに出力するか、エラーで失敗します。

一部のシェル(zsh、それが発生した場所、bashksh93mksh、FreeBSD sh)も、\uXXXX表記での$'...'表記をサポートしています。

だからあなたはできる:

echo $'\u2714\u274c'

シェルによっては、コマンドが解析されたとき(bash)、実行されたとき(zsh)、または常にUTF-8で(ksh)有効だったロケールのエンコーディングに拡張されます。

POSIXly(移植性のあるUnixライクなシステム間で)、任意のバイトシーケンスを出力する場合は、printfと8進数表記を使用する必要があります。

\xE2\x9C\x94(U + 2714のUTF-8エンコーディング)は、次のように移植可能な行に出力されます。

printf '\342\234\224\n'

そして、それをロケールの正しいエンコーディングに変換したい場合は、次のようになります。

printf '\342\234\224\n' | iconv -f UTF-8

POSIXは、システムでサポートされる可能性のある文字エンコーディングやその名前を指定しませんが、上記のコマンドは通常、UTF-8エンコーディングをサポートするPOSIXシステムで機能します。

6

生のユニコードを使用する:

$ echo -e '☑ done\n☒ fail\n☐ to do'
☑ done
☒ fail
☐ to do
0
JJoao