From: TAKAHASHI Masayoshi Date: 2001-12-06T14:10:40+09:00 Subject: [ruby-dev:15368] Re: Regexp in UTF-8 (Re: Regexp literal and Regexp.new()) 高橋征義です。 正規表現でのUTF-8問題ですが、リテラルの話に戻します。 UTF-8の正規表現リテラル中で、\x を使って文字を指定するのは、 「指定が間違ってる」ということのようですが、やっぱり何かの形 で8進または16進数をつかって文字を指定したい、ということはある と思います(というか、あります)。 とはいえ、バイト単位で指定する、というのは、曲がりなりにも 「文字(codeunit, mbchar)」の概念を持つRubyのRegexpには馴染ま ないかもしれない、という気もしてきました。 # でも、ちょっと迷ってます。 というわけで、Perl5.6.1のように \x{XXXX} という形でマルチバイト な文字を指定できるようにする、というのはどうでしょう。これなら、 何バイトあっても大丈夫ですから。 ……などと考えていたのですが、Perlの\x{XXXX}って、Unicode というかUCSのcodepointを指定してるんですね……。つまり、 UTF-8でのバイト表現とは全然違うわけで。\x{XXXX}とかっていう 4桁の16進数が、UTF-8では6バイトになってしまう、と。むーん。 さりとて、これに合わせるような指定にすると、逆にEUCやShift_JISで 不幸になってしまいそうです。まあ、EUCやShift_JISではこういう 表記は禁止する、ベタで書け、という方向性もありですが(今までも 特に苦情はありませんでしたし)、それもちと切ない。 ちなみに、Pythonでは\uXXXXでU+XXXXのUnicode文字を指定するらしい です(やっぱりベタでUTF-8のbyte sequenceを書いたりはしない)。 Javaもこうでしたっけ? なお、UnicodeのTechnical Reportでは、 \uXXXXでUCS-2(BMP)を、\UXXXXXXXX でUCS-4を指定できる、とか いうことが書いています(Perlのような書き方もアリ、という補足が ついています)。 以上を踏まえて、Rubyの正規表現リテラルでマルチバイト文字を 表現するにはどうすればよいか考えてみました。以下、「XX」は 16進文字です。 a. /foobar/ を Regex.new("foobar")と近い形にする。つまり、 \xXX で文字とは関係なく、1バイトの情報を表すことにする。 マルチバイト文字を表現する場合には、\xXX\xXX\xXX などと いう形でバイト列を並べる。 b. Perl互換。つまり、\x{XXXX} でU+XXXXにあたるUnicode文字を 指定する。Unicodeな正規表現(現状UTF-8のみ)以外では使え ない(エラー)? c. 「\xはバイト列を指定・Unicode以外にもOK」+「Unicode文字の 指定はPython/UTR互換」案。 \x{XXXXXX} が1文字分のバイト表現を指定していることにする。 (つまり、UCS-2のUnicode文字を指定する場合、UTF-8では 最大6桁の16進数で指定することになる。) Unicodeのcodepointを指定する方法としては、\uXXXXとか \UXXXXXXXXみたいなものを別途用意する。\uと\UはUnicode な正規表現以外では使えない(エラー)? d. 独自路線。「\xはバイト列を指定・Unicode以外にもOK」+ 「Unicode文字の指定はPerlとPython/UTRの折衷(?)」案。 \x{XXXXXX} が1文字分のバイト表現を指定していることにする。 Unicodeのcodepointを指定する方法としては、\u{XXXXXX}という 表記法を別途用意する。\uはUnicodeな正規表現以外では 使えない(エラー)? b案で誰も困らないのであればそれでいいと思いますが、やっぱ 困りますよねえ。というわけでc案かな? と思うのですが、 \uXXXXと\UXXXXXXXXを使い分けるのは何かと美しくないと思う ので、d案も考えました。d案は独自仕様なのが気になりますが、 形としてはすっきりしていると思います。 追記: Ruby M17NのUTF-8文字列の中で、Unicode文字を指定するには どうするか、っていう問題もありますね。 高橋征義 (TAKAHASHI Masayoshi) Email:maki@inac.co.jp