はじめまして。今井と申します。
日本語文字を扱う正規表現の仕様によくわからない点があり、投稿させていただきます。
疑問の1つは、正規表現オブジェクトの生成時とマッチ実行時で
$KCODE が違う場合にどうなるか? ということです。
はじめ、リファレンスマニュアルの
Regexp.new、正規表現リテラル、Regexp#=~、Regexp#match、組み込み変数の$KCODEの項
の説明を見て、
$KCODE の値は、マッチ実行時(Regexp#matchなど)ではなく
正規表現オブジェクト生成時(Regexp.newなど)に使われるのかな、と思いました。
しかし、実験結果と、マニュアルの Regexp#kcode の項の説明から、
実は $KCODE の値はマッチ実行時に使われるらしいことがわかりました。
仕様は、次のようなものと推測しています。
正規表現リテラルの評価 や Regexp.new の際、
リテラルのオプションやRegexp.newのcode引数によって文字コードが指定されなかった場合は、
生成された正規表現オブジェクトの kcode は nil となる。
kcode が nil である正規表現オブジェクトのマッチ実行の際は、
その時点における $KCODE の値を使用して正規表現が解釈される。
このような理解でよいでしょうか。
あるいは、そもそも、正規表現オブジェクトの生成時とマッチ時で
$KCODEを変えるというのはやってはいけない(想定されていない)のでしょうか。
この辺の仕様がわかる文書やログがあれば教えていただけるとありがたいです。
せっかく高度な機能が実装されているのによくわからないというのは残念です。
# Regexpの内部はいったいどうなってるんだろう。。
# マッチ時に必要に応じてコンパイルし直しているんでしょうか。
実験に使ったプログラムは以下のものです。
$KCODE = "NONE"
Patn = /[あ]/
Patne = /[あ]/e
$KCODE = "EUC"
Pate = /[あ]/
Patee = /[あ]/e
p Patn.kcode
p Patne.kcode
p Pate.kcode
p Patee.kcode
$KCODE = "NONE"
p Patn =~ "\xa2"
p Patne =~ "\xa2"
p Pate =~ "\xa2"
p Patee =~ "\xa2"
$KCODE = "EUC"
p Patn =~ "\xa2"
p Patne =~ "\xa2"
p Pate =~ "\xa2"
p Patee =~ "\xa2"
# "\xa2" は、EUCの'あ'の片方のバイト
これをEUCのテキストとして記述し、実行しました。
環境は、cygwin上のruby 1.8.5 (2006-12-25 patchlevel 12) [i386-cygwin] です。
(ruby -e 'p $KCODE' は 'NONE' となります)
結果は下のようになりました。
nil
"euc"
nil
"euc"
0
nil
0
nil
nil
nil
nil
nil
最初の部分を次のように置き換えても結果は変わりませんでした。
$KCODE = "NONE"
Patn = Regexp.new('[あ]')
Patne = Regexp.new('[あ]',0,'euc')
$KCODE = "EUC"
Pate = Regexp.new('[あ]')
Patee = Regexp.new('[あ]',0,'euc')
また、コマンドラインオプションの -Ke や -Kn は結果に影響しませんでした。
----
Rintaro IMAI <rinimai / yahoo.co.jp>