先日のDTPの勉強会の懇親会で、文字っ子の人が文字っ子になったキッカケ、という話題になった。
ものかのさんは「強いて言えば…」というニュアンスで「新潮文庫と岩波文庫で、同じ本の文字遣いの違いが気になったことでしょうかね。なぜこんなに違うのか。それをいろんな人に聞いたら、そういうことは当たり前に起きると聞いて、勉強を始めたんです」とのことだった。
何の本かは聞かなかったが、文脈からすると日本文学の古典であろう。
ぼくは文字っ子と言えるレベルではないので、あえて自分の例を開陳しなかったが、いまここで書いてみると、「Shift_JISで表示の表という字が文字化けするから」であった。
ものかのさんは「強いて言えば…」というニュアンスで「新潮文庫と岩波文庫で、同じ本の文字遣いの違いが気になったことでしょうかね。なぜこんなに違うのか。それをいろんな人に聞いたら、そういうことは当たり前に起きると聞いて、勉強を始めたんです」とのことだった。
何の本かは聞かなかったが、文脈からすると日本文学の古典であろう。
ぼくは文字っ子と言えるレベルではないので、あえて自分の例を開陳しなかったが、いまここで書いてみると、「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をエディタで開いてみる。
たしかに「侮ヲ」というファイルが出来ている。
これをダンプ(16進表示)してみる。
ここではWindows上のフリーウェア「xdump」を使用する。
「侮ヲ」という文字列は、16進数で0x95 8E A6であると分かる。
さて、もともと表示してほしかった「表示」という字を入力したファイルを作ってみる。
これをダンプしてみる。
「表示」という文字列は、16進数で0x95 5C 8E A6であると分かる。
逆に文字コードから、文字を検索するにはどうすればいいだろうか。
これはコード表を使う。
ここでは拙著『文字コード【超】研究』のサポートページにおいてあるwincode1.txtとwincode2.txtを見てみる。
まずwincode1.txtから、\とヲを調べてみる。
(こっちのコード表にはShift_JIS的な1バイト文字、つまり制御文字、英数字、半角カナが収められている。)
\は0x5C、ヲは0xA6であると分かる。
返す刀でwincode2.txtから、表、示、侮を調べてみる。
(こっちのコード表にはShift_JIS的な2バイト文字、つまり全角カナ、全角記号、漢字が収められている。)
表は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年代にパソコンの世界に飛び込んだぼくは、先輩が翻訳したファイルに「表\示」という文字列を発見して、ナンダコレーと思った。
ゴミだと思って取ってみると侮ヲになる。
また戻してみると正しく「表示」になる。
それをアレコレ研究しているうちに、ぼくは文字コードの摩訶不思議な世界に引きずり込まれたのである。
あなたは何をキッカケに文字っ子になりましたか。
あなたは何をキッカケにパソコンオタクになりましたか。
と、言うお題でいろんな人がブログエントリーを書くと面白いかもしれない。
当時は日本語を使う文字コードと言えば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をエディタで開いてみる。
たしかに「侮ヲ」というファイルが出来ている。
これをダンプ(16進表示)してみる。
ここではWindows上のフリーウェア「xdump」を使用する。
「侮ヲ」という文字列は、16進数で0x95 8E A6であると分かる。
さて、もともと表示してほしかった「表示」という字を入力したファイルを作ってみる。
これをダンプしてみる。
「表示」という文字列は、16進数で0x95 5C 8E A6であると分かる。
逆に文字コードから、文字を検索するにはどうすればいいだろうか。
これはコード表を使う。
ここでは拙著『文字コード【超】研究』のサポートページにおいてあるwincode1.txtとwincode2.txtを見てみる。
まずwincode1.txtから、\とヲを調べてみる。
(こっちのコード表にはShift_JIS的な1バイト文字、つまり制御文字、英数字、半角カナが収められている。)
\は0x5C、ヲは0xA6であると分かる。
返す刀でwincode2.txtから、表、示、侮を調べてみる。
(こっちのコード表にはShift_JIS的な2バイト文字、つまり全角カナ、全角記号、漢字が収められている。)
表は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年代にパソコンの世界に飛び込んだぼくは、先輩が翻訳したファイルに「表\示」という文字列を発見して、ナンダコレーと思った。
ゴミだと思って取ってみると侮ヲになる。
また戻してみると正しく「表示」になる。
それをアレコレ研究しているうちに、ぼくは文字コードの摩訶不思議な世界に引きずり込まれたのである。
あなたは何をキッカケに文字っ子になりましたか。
あなたは何をキッカケにパソコンオタクになりましたか。
と、言うお題でいろんな人がブログエントリーを書くと面白いかもしれない。