« IRIの正規化(その2) | トップページ | MD5の脆弱性を用いた証明書の偽造 »

2008.08.24

正規等価(Javaの正規表現)

前回の記事で、CANON_EQ モード(正規等価モード)の挙動がよく解らない事について触れたが、「Java 正規表現アプリケーション」というサイトで正規等価モードの挙動が解った(Javaの正規表現と正規等価については前回の記事を参照いただきたい)。

java.util.regex の実装では、正規等価モードの場合パターンをコンパイル時に正規等価である様々な分解形や合成形に展開しておき、いずれかに一致すればマッチした事になる。「Java 正規表現アプリケーション」では NFC と NFD に分解されるとあるが、実際には正規形以外にも正規等価の形があれば展開される。今回も、貞廣知行氏の「使いこなそうユニコード」中の「Unicode正規化とは」で挙げられている例を使って説明する。

「e, U+0304 (MACRON), U+0301 (ACUTE), U+0323 (DOT BELOW)」という文字列(Javaのユニコードエスケープ表現では "e\u0304\u0301\u0323"、「e macron acute dot-below」という文字を表す)は、NFDが "e\u0323\u0304\u0301"、NFC が "\u1EB9\u0304\u0301" であるが他にも正規等価の関係にある下記のような文字列に展開される(元のパターンを含む)。

  • "e\u0304\u0301\u0323"
  • "\u0113\u0301\u0323"
  • "\u1E17\u0323"
  • "e\u0304\u0323\u0301"
  • "\u0113\u0323\u0301"
  • "e\u0323\u0304\0301" (NFD)
  • "\u1EB9\u0304\0301" (NFC)

ただし、正規等価の関係に無い "e\u0323\u0301\u0304" (「e acute macron dot-below」を表す)には展開されない。これで、正しい正規等価の判定が行われる事になる。パターン側のみを展開するため、判定対象の文字列は元のまま一切変更されない(そのため、前の記事の通り文字数も元のままのコードポイントによって数えられる)。

しかし、「Java 正規表現アプリケーション」にもある通り、正規等価モードにはバグがあるため残念ながら全ての場合に正しい正規等価の判定が行われる訳ではない。Fixしていない既知のバグは2種類である。

1つは、分解(または合成)される文字が2個以上連続すると Pattern#compile が例外を投げるというバグである(Bug ID: 6728861)。例えば、"ギガント" のように濁音が2個以上連続する場合は例外になる。

もう1つは、「合成除外文字」が決してマッチしないというバグである(Bug ID: 6736245)。このため、オングストローム(Å)のような記号や互換漢字は正規等価ではマッチしない(たとえ、自分自身であっても)。これは、パターンの展開時に行われる合成に正規合成用のテーブルを流用している事が原因と考えられる。

この他にも、正規等価モードには文字クラスの扱いが特殊であるという問題もある。文字クラスの範囲のどちらかの端に合成文字が含まれていた場合、範囲指定そのものが無効になり、両端の文字にのみマッチするようになる。具体的に言えば "[か-ご]" は本来 "[かがきぎくぐけげこご]" の意味になるが、正規等価モードで "[か-ご]" と記述した場合には、単に "(?:か|ご)" と記述した事と等価になる。この動作はバグにようにも見えるが、正規等価の定義「2つの文字列の正規分解が等しい」に照らして考えると、"[か-ご]" を正規分解した場合に意図しないパターンになる("[か-こ\u3099]"となり全ての濁音にヒットする)ため、規格上の動作は未定義と言うべきだと考える。

以上に挙げたように、正規等価モードには仕様上の疑問点やバグが残っている。確実な動作を狙うのであれば、正規等価モードを使用するのではなく、"(?:が|か\u3099)" のように明示的に展開するのが良いであろう。

« IRIの正規化(その2) | トップページ | MD5の脆弱性を用いた証明書の偽造 »

パソコン・インターネット」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: 正規等価(Javaの正規表現):

« IRIの正規化(その2) | トップページ | MD5の脆弱性を用いた証明書の偽造 »

最近のトラックバック

無料ブログはココログ

Googleアナリティクス

  • Googleアナリティクス