先日のDTPの勉強会の懇親会で、文字っ子の人が文字っ子になったキッカケ、という話題になった。

ものかのさんは「強いて言えば…」というニュアンスで「新潮文庫と岩波文庫で、同じ本の文字遣いの違いが気になったことでしょうかね。なぜこんなに違うのか。それをいろんな人に聞いたら、そういうことは当たり前に起きると聞いて、勉強を始めたんです」とのことだった。

何の本かは聞かなかったが、文脈からすると日本文学の古典であろう。





ぼくは文字っ子と言えるレベルではないので、あえて自分の例を開陳しなかったが、いまここで書いてみると、「Shift_JISで表示の表という字が文字化けするから」であった。
Windows 3.1時代(1993年前後)、パソコンの会社に転職した。
当時は日本語を使う文字コードと言えばWindowsもMacもShift_JIS、UNIXはEUC-JPだった。

WindowsのUIを翻訳するのに「リソース」ファイル(拡張子は.rc)を編集した。
たとえばメニューだとこうなっている。

「File Edit View Help」

これをこう翻訳する。

「ファイル 編集 表示 ヘルプ」

それでいいはずだが、なぜか前のバージョンのファイルを見ると、変な\が入っていた。

「ファイル 編集 表\示 ヘルプ」

最初は間違いかと思っていたが、あまりにも表示の表の後ろに\が入っているので、これはわざと入れているのだろうと思った。

Shift_JISの\は0x5Cで、日本語フォントでは円記号¥、欧文フォントではバックスラッシュ\である。
「K&R」を買ってC言語の勉強をした人が、

 printf("Hello, world!\n");

という例文を打ち込もうとして、\というキーを探し求めて挫折した、という都市伝説がまことしやかに広まっている。



これは日本人が日本語環境のWindowsを使う場合は、

 printf("Hello, world!¥n");

と書くべきである。

他に、Windowsでは階層フォルダーのパス区切り文字に使われている。欧米では

 C:\Users\

というフォルダーが、日本では

 C:¥ユーザー¥

になる。

こんなコンピューター的に重要な文字コードのグリフが日本と欧米で違うのは大問題だ。
ちなみにUnicodeでは半角の\と¥は違う字である。
お手元のiPhoneで確かめられると良い。

この後は全部半角の\で通す。
ブラウズされている環境で半角の¥になったり\になったりすると思うが、適宜読み替えていただきたい。
\の文字コードは0x5Cだ。

さて、ここからはPerlで書く。

 #! /bin/perl
 # sayHello.pl -- Perlであいさつする

 print "こんにちは!\n";

上のプログラムをShift_JISで保存し、PerlがインストールされたWindowsのコマンドラインで実行すると、

 C:\Perlperl> sayHello.pl
 こんにちは!

と表示される。
プログラムをShift_JISで書くとコマンドラインに正常に表示されるのは、WindowsのコマンドラインがShift_JISを表示するようにデフォルトでは設定されているからだ。

ここで、\nは「改行」のことである。
このように、\に続けて何らかの字を書き、目に見えない文字コードを表現することを「エスケープシーケンス」と言う。
\はエスケープシーケンスの始まりを意味する。
\tはタブ文字を表す。
\bはベルコードを表し、これを表示するとパソコンがチン(またはブー)と言う。

次のプログラムは「\nと書くと改行が出てくる」という、Perlの使い方を説明するものである。

 #! /bin/perl
 # nUsage.pl -- \nの使い方を表示する(バグっている)

 print "改行を書くには\nと書きます!\n";

使ってみる。

 C:\Perlperl> nUsage.pl
 改行を書くには
 と書きます!

ダメだー。
最後の\nは改行を出して欲しかったのだが、途中の\nは「\n」という文字列をそのまま出して欲しかった。
ところが、コンピューターにしてみれば、\nと言われたら、「\n」ではなくて改行を表示するしかないので、上記のようなダメダメな表示になってしまった。

こういうときは、こうする。

 #! /bin/perl
 # nUsage.pl -- \nの使い方を表示する(バグ修正)

 print "改行を書くには\\nと書きます!\n";

これでオッケーなはずである。

 C:\Perlperl> nUsage.pl
 改行を書くには\nと書きます!

やったー。

これは、\\というエスケープシーケンスが\という文字そのものを表すからである。
つまり、""中に\そのものを書きたいときは\\と書く。

なお、エスケープシーケンス的に意味がないところで\を書くと、その\は単純に無視される。

 #! /bin/perl
 # nUsage.pl -- \nの使い方を表示する(バグ修正)
 
 print "\改\行\を\書くには\\nと書きます!\n";

最初の方にパラパラッと意味もなく\をちりばめてたが、表示は変わらない。

 C:\Perlperl> nUsage.pl
 改行を書くには\nと書きます!

つまり、意味もなく挿入された4つの\は無視されている。

まとめると:
 ・\nは改行、\tはタブ、\bはベルになる。これをエスケープシーケンスという
 ・\\は\になる
 ・エスケープシーケンス的に意味のない文字の前の\は無視される

さて、次のプログラムを実行してみる。

 #! /bin/perl
 # hyouji.pl -- 文字列を表示する(バグっている)

 print "Perlで文字列を表示します!\n";

これを実行してみると、奇怪な現象が起きる。
(あくまでShift_JISを使ったときのみ起きる現象である。)

 C:\Perl\perl>hyouji.pl
 Perlで文字列を侮ヲします!

「表示」という文字列が「侮ヲ」(侮辱の侮に半角カナのヲ)と文字化けしている。

これはなぜだろうか。

分からないなりに「表示」とだけ表示してみる。

 #! /bin/perl
 # hyouji.pl -- 文字列を表示する(バグっている)

 print "表示";

どうだろう。

 C:\Perl\perl>hyouji.pl
 侮ヲ

当然ダメだ。

これを、画面に表示しないでファイルにリダイレクトしてみる。

 C:\Perl\perl>hyouji.pl > test.txt

すると、画面には何も表示されず、test.txtというファイルが作成される。

このtest.txtをエディタで開いてみる。

buo


たしかに「侮ヲ」というファイルが出来ている。

これをダンプ(16進表示)してみる。
ここではWindows上のフリーウェア「xdump」を使用する。

buodump


「侮ヲ」という文字列は、16進数で0x95 8E A6であると分かる。

さて、もともと表示してほしかった「表示」という字を入力したファイルを作ってみる。

hyouji


これをダンプしてみる。

hyoujidump


「表示」という文字列は、16進数で0x95 5C 8E A6であると分かる。

逆に文字コードから、文字を検索するにはどうすればいいだろうか。
これはコード表を使う。
ここでは拙著『文字コード【超】研究』のサポートページにおいてあるwincode1.txtとwincode2.txtを見てみる。



まずwincode1.txtから、\とヲを調べてみる。
(こっちのコード表にはShift_JIS的な1バイト文字、つまり制御文字、英数字、半角カナが収められている。)
wincode1


\は0x5C、ヲは0xA6であると分かる。

返す刀でwincode2.txtから、表、示、侮を調べてみる。
(こっちのコード表にはShift_JIS的な2バイト文字、つまり全角カナ、全角記号、漢字が収められている。)

wincode2


表は0x955C、示は0x8EA6、侮は0x958Eであると分かる。

つまりこういうことである。

 print "表示";

というプログラムは、「表示」という文字列を表示するために、0x955C 8EA6を出力しようとした。
ところが、表の後半の0x5Cは\という字だったため、消失してしまった。
よって、0x95 8E A6と出力された。
ここで、最初の0x95(表の前半)と、2バイト目の0x8E(示の前半)が合体してしまい、0x958E(侮)になってしまった。
よって、示の後半の0xA6が千切れて残り、ヲとして表示されたわけである。

では、これを修正するにはどうすればいいだろうか。

根本的な解決ではないが、当時としてはこういうワークアラウンド(弥縫策)が取られていた。

 #! /bin/perl
 # hyouji.pl -- 文字列を表示する(修正した)

 print "表\示";

表と示の間に\と入れてみた。
実行してみる。

 C:\Perl\perl>hyouji.pl
 表示

あはは出来てるよ。

どういうことか分かりますか。

 print "表\示";

は、"表\示"とprintすることにより、「0x955C 5C 8EA6」を出力しようとした。

ところが、この中の0x5C5Cは、つまり\\であって、\1個に置換される。
よって、0x5C5Cは0x5Cとなり、「0x955C 8EA6」というコードが出力され、結果的に「表示」と正しく表示される。

これは、Shift_JIS漢字コードの後半1バイトが0x5Cである文字についてすべて起こる問題である。
他に「申告の申」や「全角カタカナのソ(!)」がある。
他にもいっぱいある。
こういう字をいちいち覚えておいて、そのたびに\を挿入すればいいのだろうか。
それとも、当たるを幸い\をちりばめればいいのだろうか。
どっちもゾッとしない。

現在では、WindowsのリソースもPerlのプログラムもUnicodeで書くことが標準的であって、この問題はもはや起きない。
しかし90年代のShift_JISコンピューターではこの問題を多発していて、エンジニアはその都度\を挿入するのが仕事であった。

上の文章は順序良く知識を書いているので、大した話じゃないと思われるだろうが、90年代にパソコンの世界に飛び込んだぼくは、先輩が翻訳したファイルに「表\示」という文字列を発見して、ナンダコレーと思った。
ゴミだと思って取ってみると侮ヲになる。
また戻してみると正しく「表示」になる。
それをアレコレ研究しているうちに、ぼくは文字コードの摩訶不思議な世界に引きずり込まれたのである。

あなたは何をキッカケに文字っ子になりましたか。
あなたは何をキッカケにパソコンオタクになりましたか。
と、言うお題でいろんな人がブログエントリーを書くと面白いかもしれない。

Subscribe with livedoor Reader
Add to Google
RSS
このエントリーをはてなブックマークに追加