UnicodeとRegular Expression

JavaAPIドキュメントのjava.util.regex.Patternを眺めると、regular expressionのUnicodeサポートに関しては「UTS #18: Unicode Regular Expressions」のLevel1であるBasic Unicode Support、プラスRL2.1 Canonical Equivalrentsとあるように、Java言語ではLevel1, 2, 3のうちLevel1とLevel2のごく一部、2.1のCanonical Equivalentsのみのサポートとなっています。他の言語でのサポート状況はどうなのか、、、は「http://www.regular-expressions.info/refflavors.html;title」に一覧表の形式で詳しくまとめられていました。ここには各種言語の(というよりは各regular expression engineの)、様々なregular expressionの機能比較があるのですが、その中に"Unicode Characters", "Unicode Properties, Scripts and Blocks"という二つの表があり、Unicodeによるregular expressionsへの対応が一目で比較できるようになっています。この表を見ると、Perlがとにかくすばらしいです。Unicodeでregular expressionsを使うならPerlにするべきか?!と思うほど。


Java言語もそれなりに健闘していて、http://d.hatena.ne.jp/yokolet/20080725#1217008076で試したように、\u30fcのようなUnicode Charactersを使ったregular expressionが可能ですが、他にも \p{InGreek}(GreekとCopticのブロック;U+0370...U+03FF)や\P{InGreek}(GreekとCopticのblock以外)、\p{Sc}(Currency Symbolsのブロック)といったregular expressionを指定可能です。例えば、「Unicode/UTF-8-character table」にUnicodeのコードポイントと対応する文字の一覧があるので、これを見ながら\p{InGreek}をhttp://d.hatena.ne.jp/yokolet/20080725#1217008076で使ったJavaのコードで試してみました。

r[egex], i[nputs] or e[xit]? 
r
regex? \p{InGreek}
r[egex], i[nputs] or e[xit]? 
i
inputs? abcϴΩΣあいう
Found "ϴ" starting at 3 and enging at 4.
Found "Ω" starting at 4 and enging at 5.
Found "Σ" starting at 5 and enging at 6.
r[egex], i[nputs] or e[xit]? 
i
inputs? abcあいう
No match found.
r[egex], i[nputs] or e[xit]?

というように、指定したUnicodeブロックのマッチングができました。


ちょっと不思議なマッチング結果になるけれど、使う方としては自然かも、、、と思うのが \p{Sc}の通貨ブロック指定です。Currency Symbolsのブロックというのは「Regex Tutorial - Unicode Characters and Properties」や「Unicode/UTF-8-character table("go to other blockの"ドロップダウンメニューでU+20A0...U+20CF: Currency Symbolsを選ぶ)」に出ているように、Unicodeのコードポイント、U+20A0からU+20CFの範囲となっています。ここには$(ドル)も無ければ、¥(円)もありません。かわりに、この二つや¢(セント)などはU+0000からU+007Fの範囲、Basic_Latinにあります。ところが、Java言語で\p{Sc}を指定すると、

r[egex], i[nputs] or e[xit]? 
r
regex? \p{Sc}
r[egex], i[nputs] or e[xit]? 
i
inputs? これは$19.99です
Found "$" starting at 3 and enging at 4.
r[egex], i[nputs] or e[xit]? 
i
inputs? これは¥100です 
Found "¥" starting at 3 and enging at 4.
r[egex], i[nputs] or e[xit]? 
i
inputs? これは€100です
Found "€" starting at 3 and enging at 4.
r[egex], i[nputs] or e[xit]? 
i
inputs? これは©100です
No match found.
r[egex], i[nputs] or e[xit]?

のように、Basin_Latinの範囲に存在していても($と¥)、Currency Symbolsの範囲に存在しているもの(€:ユーロ)は当然、通貨記号はマッチしてくれます。一方、Basin_Latinの範囲にある©は通貨ではないのでマッチしないという結果でした。


Regular ExpressionにUnicodeが入ってくると奥が深いです。