30
4

1 に答える 1

36

UTF-8 でエンコードされた文字列"[一-龠々〆ヵヶ]"は、次のようになります"[\xe4\xb8\x80-\xe9\xbe\xa0\xe3\x80\x85\xe3\x80\x86\xe3\x83\xb5\xe3\x83\xb6]"。そして、これはあなたが探しているドロイドキャラクター クラスではありません。

探している文字クラスは、以下を含むものです。

  • U+4E00..U+9FA0 の範囲の任意の文字。また
  • 々、〆、ヵ、ヶのいずれかの文字。

指定した文字クラスは、以下を含むものです。

  • 「文字」\xe4 または \xb8 のいずれか。また
  • \x80..\xe9 の範囲内の任意の「文字」。また
  • 「文字」のいずれか \xbe、\xa0、\xe3、\x80、\x85、\xe3 (再び)、\x80 (再び)、\x86、\xe3 (再び)、\x83、\xb5、\xe3 (再び)、\x83 (再び)、\xb6。

めんどくさいですよね?問題が見えますか?

これは、「ラテン」文字 (az のようなものを意味していると思います) とは一致しません。UTF-8 では、それらはすべて 0x80 未満の 1 バイトを使用し、その乱雑な文字クラスには含まれないためです。

3つの「文字」があり、正規表現はその奇妙な長いリストから1つの「文字」のみに一致"中"するため、どちらにも一致しません。"中"試してみてassert(std::regex_match("中", std::regex("...")))ください。

追加すると、奇妙な長いリストにこれらの「文字」が3つ+含まれているため"中"、正規表現が1つ以上に一致するため機能します。

代わりに追加する{1}と、3 つの「文字」を 1 つに対して照合することに戻るため、一致しません。

ちなみに、3 つの「文字」を同じ 3 つの「文字」に対して同じ順序で照合しているため、一致します"中""中"

正規表現は、+順序を気にしないため、実際には望ましくないものと一致します。そのバイト リストから UTF-8 で作成できる任意の文字が一致します。"\xe3\x81\x81"(ぁ U+3041) にマッチし、 のような無効な UTF-8 入力にもマッチします"\xe3\xe3\xe3\xe3"

より大きな問題は、最低限必要な Unicode のレベル 1 サポートさえない正規表現ライブラリを使用していることです。それはバイトを変更し、あなたの貴重な小さな正規表現がそれについてできることはあまりありません.

さらに大きな問題は、ハードコードされた文字セットを使用して「日本語の漢字または漢字」を指定していることです。そのために Unicode Script プロパティを使用しないのはなぜですか?

R"(\p{Script=Han})"

そうそう、これは C++11 正規表現では機能しません。しばらくの間、それらが Unicode では役に立たないよりも厄介なほど悪いことをほとんど忘れていました。

それで、あなたは何をすべきですか?

入力を a にデコードし、すべてをマッチングにstd::u32string使用できます。char32_tそれはあなたにこの混乱を与えることはありませんが、「特定のプロパティを共有する一連の文字」を意味する場合、範囲と例外をハードコーディングすることになります.

C++11 正規表現のことは忘れて、 ICUのような最低限のレベル 1 Unicode サポートを持つ正規表現ライブラリを使用することをお勧めします。

于 2013-04-09T07:21:38.687 に答える