たまに漢字にマッチする正規表現パターンを書きたいときがあります。Perl の正規表現だと Unicode のスクリプト名を使って \p{Han}
で漢字にマッチさせられるのですが、JavaScript ではそうはいきません。JavaScript の正規表現には以下のふたつの問題があります。
\p{...}
) に対応していない。/u
フラグで解決する見込み。とはいえ、解決不能な問題というわけでもないので、Perl の \p{Han}
を JavaScript に移植してみましょう。\p{Han}
の範囲は以下のコマンドで参照できます。
perl -MUnicode::UCD -MData::Dumper -E 'say Dumper Unicode::UCD::charscript("Han");'
Perl 5.20.2 (Unicode 6.3.0) では以下の範囲が含まれるとわかりました。
U+2E80
- U+2E99
U+2E9B
- U+2EF3
U+2F00
- U+2FD5
U+3005
- U+3005
U+3007
- U+3007
U+3021
- U+3029
U+3038
- U+303B
U+3400
- U+4DB5
U+4E00
- U+9FCC
U+F900
- U+FA6D
U+FA70
- U+FAD9
U+20000
- U+2A6D6
(\uD840\uDC00
- \uD869\uDED6
)U+2A700
- U+2B734
(\uD869\uDF00
- \uD86D\uDF34
)U+2B740
- U+2B81D
(\uD86D\uDF40
- \uD86E\uDC1D
)U+2F800
- U+2FA1D
(\uD87E\uDC00
- \uD87E\uDE1D
)サロゲートペアが [\uD800-\uDBFF][\uDC00-\uDFFF]
であることを踏まえると、BMP 外の範囲はそれぞれ以下の部分的な範囲に展開できます。
\uD840\uDC00
- \uD869\uDED6
[\uD840-\uD868][\uDC00-\uDFFF]
\uD869[\uDC00-\uDED6]
\uD869\uDF00
- \uD86D\uDF34
\uD869[\uDF00-\uDFFF]
[\uD86A-\uD86C][\uDC00-\uDFFF]
\uD86D[\uDC00-\uDF34]
\uD86D\uDF40
- \uD86E\uDC1D
\uD86D[\uDF40-\uDFFF]
\uD86E[\uDC00-\uDC1D]
\uD87E\uDC00
- \uD87E\uDE1D
\uD87E[\uDC00-\uDE1D]
これらを整理して組み合わせると、最終的に以下のパターンが得られます。
/(?:[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u3005\u3007\u3021-\u3029\u3038-\u303B\u3400-\u4DB5\u4E00-\u9FCC\uF900-\uFA6D\uFA70-\uFAD9]|[\uD840-\uD868][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|[\uD86A-\uD86C][\uDC00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D])/
というわけで「漢字 1 文字にマッチする JavaScript の正規表現パターン」でした。よいお年を。
コメントをする