今回は任意の文字を表示してみます。1970年代なら8ビット範囲の文字が表示できれば十分でした。1980年代に入ると日本語など2バイト以上でないと表現できない文字が出てきました。そしてUnicode(ユニコード)の時代になると可変長の複数のバイト、つまりマルチバイトで表現される文字が圧倒的に多くなりました。(Unicode 16.0では154998文字が登録済み)
・Unicode 16
https://www.unicode.org/versions/Unicode16.0.0/
コンピュータで表現できる文字は、まだまだ増えるでしょう。例えば日本語でも変体仮名などもありますし、古いコンピュータ上で使われていた独特の文字などまだ未登録なものは多いからです。
今回はechoコマンドで文字を表示しますが、Unicode文字の表現指定は他のコマンドでも同じです。また、書体(フォント)の関係ですべての文字が表示できない事もあります。ここらへんは実行環境によって、かなり違いが出ます。このためコマンドを実行した結果が異なってしまう場合がありますので、この点に関してはご容赦ください。さらにUnicodeゆえの表現(合成される種類の文字)がうまく表示されないことがあります。その場合、出力されたテキストをコピーしUnicodeの文字表現が正しく処理されるアプリケーションなどにペーストしてください。
1バイト文字を表示する
今さら書く必要もなさそうですが、まずはechoコマンドで英数字を表示してみましょう。
以下のようにすると1234の文字が表示(出力)されます。
echo 1234
以下のようにシングルクオーテーションで囲んでも同じ結果になります。
echo '1234'
ダブルクオーテーションで囲む事もできます。ただし記号などが含まれるとシェルによって展開が行われて指定した文字がそのまま表示されない場合があります。
echo "1234"
記号などを、そのまま表示したい場合はシングルクオーテーションで囲みます。囲まなくても表示できるものもありますが、シングルクオーテーションで囲んだ方が確実です。
制御文字/エスケープシーケンス
キーボードから入力できる英数字や記号であればよいのですが、コンピュータに割り当てられている文字にはキーボードから入力できない文字もあります。Unicode文字も入力できないものも多数ありますが、1バイト文字でも入力できないものがあります。例えば改行です。改行したい文字列の途中でキーボードから入力してしまうと本当に改行されてしまい文字列の途中で改行されることはなくなってしまいます。
このような場合、バックスラッシュ(\)を使って指定します(エスケープシーケンス)。バックスラッシュの後にnの文字を指定することで改行コードとして指定することができます。echoコマンドの場合、エスケープシーケンスを解釈させるために-eを指定する必要があります。(macOS+zshの場合は-e無しでも処理されます)
以下のようにすると123の後に改行され次の行に456が表示されます。
echo -e '123\n456'
バックスラッシュの後に指定する文字によって様々な動作を指定できます。ただし、音を出すBellのコードなどすべての環境で同じように動作する保証はありません。指定できる主な文字を以下に示します。
\n | 改行 |
---|---|
\r | 復帰 |
\t | 水平タブ |
\b | 後退・バックスペース |
\a | ベル |
日本語を表示する
次に日本語を表示してみましょう。日本語を表示する場合はシングルクオーテーションかダブルクオーテーションで囲みます。
echo '日本書紀とは?'
echo "源氏物語とは?"
環境にもよりますが、絵文字なども表示する事ができます。
echo '☺️'
絵文字などを入力できる環境であれば問題ありませんが、そうでない場合は困ってしまいます。そのような場合、次に説明するUnicode番号を指定する方法を使う事になります。
Unicode番号を指定して表示する
次にUnicodeの番号を指定して文字を表示してみましょう。Unicodeで番号を指定する場合、2種類あります。文字の割り当て番号が16ビット範囲内の場合は\uの後に16進数で指定します(英文字は大文字でも小文字でも問題ありません)。\uのあとは1桁以上の番号を指定できます。\u31でも\uのあとは1桁以上の番号を指定できます。\u0031でも同じ結果(意味)になります。
以下のようにUnicodeを指定すると平仮名の「あ」が表示されます。
echo -e '\u3042'
平仮名の「い」であれば以下のようになります。
echo -e '\u3044'
Unicodeの文字は連続して指定することもできます。以下のようにすると「なんとなくコマンド」の文字が表示されます。
echo -e '\u306A\u3093\u3068\u306A\u304F\u30B3\u30DE\u30F3\u30C9'
\uの後の番号を変えれば様々な文字を表示することができます。ただし\uでの指定方法ではUnicode 16.0での15万文字を表現することができません。\uは16ビット範囲、つまり0〜65535までしか表現できないためです。これ以上の文字番号を指定するには\Uを使います。uが大文字か小文字かで表現できる範囲が違うわけです。ちなみに16ビット以下の場合に\Uを使って指定しても問題ありません。
それではピラミッドで有名なエジプトのヒエログリフを表示してみましょう。ヒエログリフの文字コードの割り当ては以下のようになっています。最初のヒエログリフの文字コードが13000なので16ビット範囲では収まっていない値になっています。
Egyptian Hieroglyphs
https://www.unicode.org/charts/PDF/U13000.pdf
以下のようにするとヒエログリフが表示されます。ただし、対応する書体(フォント)がない場合、文字がないことを示す文字が表示されます。以下の例ではmacOSの書体(フォント)には該当するヒエログリフがあるのにラズベリーパイの書体(フォント)には無いことがわかります。
echo -e '\U13000'
ここで小文字のuにしてコマンドを入力するとヒエログリフではなく違う文字が表示されてしまいます。
echo -e '\u13000'
文字のUnicode番号がわかれば絵文字でも何でも表示できます。ただし、書体(フォント)に該当する文字が用意されていなければ期待する文字は表示されません。また英文字に限らず書体によってデザインが異なる点にも注意が必要です。例えば絵文字をゲーム等で利用した場合、環境によってかなり印象が変わってしまいます。
echo -e '\U1F30F'
絵文字の中には時計で時刻を示すものも用意されているのでプログラム(シェル等)で時間を取得して絵文字で出力するといった使い方もありかもしれません。
echo -e '\U1F550'
・macOS+zsh用(時計の絵文字を連続表示するシェルスクリプト)
for i in {$((0x1F550))..$((0x1F55B))}; do printf "$(printf '\\U%x' $i)\n"; done
Macで使われる特殊文字
Macで使われる特殊なキーはUnicodeとして登録されています。
例えばコマンドキーを示すマークを表示する場合は以下のようになります。
echo -e '\u2318'
他にもいろいろ用意されています。
echo -e '\u21E7'
echo -e '\u2325'
echo -e '\u2303'
echo -e '\u21A9'
その他の記号については以下のページで参照できます。
Unicode一覧 2000-2FFF
https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_2000-2FFF
WindowsキーのマークはUnicode文字としては登録されていないようです。手軽なところでは田んぼの田で代用できなくはない気もします。それは嫌だというのであれば、それらしい文字を探してきて使うという手もあります。例えば以下のような番号の文字です。(一応これはジョークネタです)
echo -e '\U1030E'
どうしてもWindowsキーのマークを使いたい場合は書体(フォント)を作成するかUnicodeのPrivate Use Area(U+E000からU+F8FFなど他にもあります)を利用して外字扱いにしてしまう方法もあります。ただ、これは他の環境で正常に表示されないので、使用できる範囲は限定されることになります。
結合文字
Unicodeはなかなか面倒な部分もありますが、便利な部分もあります。最後に結合文字を表示して終わりにしましょう。
さきほど「なんとなくコマンド」の文字を以下のようにして表示させました。
echo -e '\u306A\u3093\u3068\u306A\u304F\u30B3\u30DE\u30F3\u30C9'
それでは結合文字を使って同じように表示してみます。
echo -e '\u306A\u3093\u3068\u306A\u304F\u30B3\u30DE\u30F3\u30C8\u3099'
指定した文字コードは違うのに表示される結果は同じように見えます。これがUnicodeでのトラブルの原因の1つです。同じように見える文字でも内部表現が異なっているためです。
また、存在しないような仮名も表現できてしまうことになります。通常日本語の「ト」には濁点はつきますが、半濁点(右上に小さい○)はつきません。でも、Unicodeならつけることができます。以下のように指定するとトに半濁点がついて表示されます。
echo -e '\u306A\u3093\u3068\u306A\u304F\u30B3\u30DE\u30F3\u30C8\u309A'
ちなみに数字の7に半濁点をつけると以下のようになります。
echo -e '7\u309A'
半濁点を2つ連続させることもできます。が、こうなってしまっては一体何と読むのかわかりません。
echo -e 'え\u309A\u309A'
後から自由に濁点、半濁点を付けることができる仕様なのは便利な面もあれば不便な面もあります。例えば漫画等で「あ」に濁点をつけるようなこれまでにない仮名表現には便利です。
最終的に見た目だけで決定される世界であれば内部の表現方法がどうであれ問題は大きくなりません。これが文字の検索・置換をするとなると、なかなかにして大変です。異体字もどうするのかなど、異体字だけに頭の痛い字・・・(以下略)
Unicodeではプログラムでうまく処理できるように正規化(NFC,NFD,NFKC,NFKD)する必要があったり、内部がUTF-8なのかUTF-16なのかUTF-32なのか文字の表現方法も数種類あり大変です。Unicodeは見た目1つの文字コードなのに中身はドロドロという綺麗さと汚さを持っています。いかにも人間らしい感じのする文字コードではないでしょうか。
といったところで泥沼に沈む前に終わりにしましょう。