Ruby 1.9のUnicode Regular Expressions再び

新しいRuby 1.9ならUnicode Regular Expressionsがエラーにならないとの指摘をいただいたので、試してみました。Ubuntuのパッケージマネージャでは歳インストールしても古い1.9しかインストールされないので、ftp://ftp.ruby-lang.org/pub/ruby/1.9からruby-1.9.0-3.tar.gzをダウロードしてコンパイルしました。こんどは、ruby 1.9.0 (2008-07-25 revision 18217) という新しいバージョンの1.9です。

指摘をいただいたように、Rubyファイルの冒頭に Pythonと同様のエンコード指定を追加しましたので、

# -* coding: UTF-8 -*-

require 'strscan'

def strscan_regexp(str, re)
  puts re
  s = StringScanner.new(str)
  until s.eos?
    s.skip(/\s*/)
    case
      when s.scan(/(\w+)|([^\s\w]+)/)
        if s[0] =~ re
          puts "<<#{$&}>>"
        end
    end
  end
end

となりました。ここで、いろいろ試したところ、

strscan_regexp("a b c あ い う ア イ ウ", /\p{Hiragana}/u)
strscan_regexp("a b c あ い う ア イ ウ", /\p{^Hiragana}/u)
strscan_regexp("a b c あ い う ア イ ウ", /[\u3040-\u309F]/)
strscan_regexp("It is $19.99.", /\p{Sc}/)
strscan_regexp("これは¥100。", /\p{Sc}/)
(?-mix:\p{Hiragana})
<<あ>>
<<い>>
<<う>>
(?-mix:\p{^Hiragana})
<<a>>
<<b>>
<<c>>
<<ア>>
<<イ>>
<<ウ>>
(?-mix:[\u3040-\u309F])
<<あ>>
<<い>>
<<う>>
(?-mix:\p{Sc})
<<$>>
(?-mix:\p{Sc})
<<¥>>

のような結果になり、unicode regular expressionsが使えるようになっているのでした。

ただ、negationはUTS #18: Unicode Regular Expressionsで決められている書式\P{property_name}(大文字Pを指定する)とは若干違っていて、Onigurumaスタイル(?)の \p{^property-name}のみとなっていました。ちなみに、UTS #18: Unicode Regular Expressionsにあるのは、

POSITIVE_SPEC := ("\p{" PROP_SPEC "}") | ("[:" PROP_SPEC ":]")
NEGATIVE_SPEC := ("\P{" PROP_SPEC "}") | ("[:^" PROP_SPEC ":]")

です。試しに、数字についてPOSIXスタイルの[: name:]の表記の試してみると、

strscan_regexp("a 1 あ ア", /\p{Nd}/)
strscan_regexp("a 1 あ ア", /\p{^Nd}/)
strscan_regexp("a 1 あ ア", /[:Decimal_Number:]/)
strscan_regexp("a 1 あ ア", /[:^Decimal_Number:]/)
?-mix:\p{Nd})
<<1>>
(?-mix:\p{^Nd})
<<a>>
<<あ>>
<<ア>>
(?-mix:[:Decimal_Number:])
<<a>>
(?-mix:[:^Decimal_Number:])
<<a>>

という結果でした。最後の二つはエラーにならないものの、正しい結果にはなりませんでした。Ndの別名はhttp://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txtで見つけたものです。


もうひとつ。昨日のエントリで「なんと、/\p{Alpha}/uはアルファベットだけではなくて、ひらがな、カタカナまでマッチしてしまいました。」と書いたのですが、OnigurumaはUnicodeの場合、\p{Alpha}はLetterを意味するので、この結果は正しいものでした。アルファベットだけマッチさせたい場合は、\p{Latin}でした。


昨日のエントリで抜粋したRegular Expressions Reference Table of Contentsの表はかなり書き変わりそうですね。