none
正規表現検索を行う場合、IVSやサロゲートペア文字列を1文字として判定するには? RRS feed

  • 質問

  • Dim m1 As System.Text.RegularExpressions.Match
    Dim m2 As System.Text.RegularExpressions.Match
    m1 = System.Text.RegularExpressions.Regex.Match("AあB", "A.B")
    m2 = System.Text.RegularExpressions.Regex.Match("A𠮟B", "A.B")

    上記のような場合、m1.SuccessはTrueとなりますが、m2.SuccessはFalseとなります。

    「𠮟」はU+20B9FでUTF16上ではサロゲートペアの文字となります。同様にIVS文字がAとBの間にあったとしても検索できません。

    検索文字列「A.B」でm1とm2のSuccessがTrueとなる方法は無いものでしょうか?

    Regex にIVSやサロゲートペアを1文字とみなすようなオプションがあるとありがたいのですが・・・

    2017年5月17日 12:35

回答

  • StringクラスのChar オブジェクトと Unicode 文字

    文字列内の各文字は、Unicode のスカラー値によって定義されます。これは Unicode のコード ポイントまたは Unicode 文字の序数値とも呼ばれます。 各コード ポイントは UTF-16 エンコーディングを使用してエンコードされ、エンコーディングの各要素の数値は Char オブジェクトで表されます。

    単一の Char オブジェクトは通常、単一のコード ポイントを表します。つまり、Char の数値はコード ポイントと等しくなります。 たとえば、文字 "a" のコード ポイントは U+0061 です。 しかし、1 つのコード ポイントに対して、複数のエンコード要素 (複数の Char オブジェクト) が必要になることがあります。 Unicode 標準は、複数の Char オブジェクトに対応する 3 種類の文字を定義します (書記素、Unicode の補助コード ポイント、および補助平面の文字)。

    書記素は、1 つの基本文字と、その後に続く 1 つ以上の組み合わせ文字で表されます。 たとえば、文字 ä は Char オブジェクト (コード ポイント U+0061) とその後の Char オブジェクト (コード ポイント U+0308) によって表されます。

    と説明されているように、1文字がCharオブジェクト1つとは限りません。またIVSとサロゲートペアを挙げられていますが、それ以外にも引用したように書記素;graphemeもありますし、Unicodeとは? その歴史と進化、開発者向け基礎知識には1文字で38バイトにもなる絵文字が挙げられています。何をもって1文字とするかで大きく変わりますからどうしようもないかと思います。

    その上であえて挙げるならば、正規表現の文字クラスには \p{Cs} がサロゲート(U+D800~U+DFFF)を指しますのでこれを活用するぐらいでしょうか。

    2017年5月17日 12:59

すべての返信

  • StringクラスのChar オブジェクトと Unicode 文字

    文字列内の各文字は、Unicode のスカラー値によって定義されます。これは Unicode のコード ポイントまたは Unicode 文字の序数値とも呼ばれます。 各コード ポイントは UTF-16 エンコーディングを使用してエンコードされ、エンコーディングの各要素の数値は Char オブジェクトで表されます。

    単一の Char オブジェクトは通常、単一のコード ポイントを表します。つまり、Char の数値はコード ポイントと等しくなります。 たとえば、文字 "a" のコード ポイントは U+0061 です。 しかし、1 つのコード ポイントに対して、複数のエンコード要素 (複数の Char オブジェクト) が必要になることがあります。 Unicode 標準は、複数の Char オブジェクトに対応する 3 種類の文字を定義します (書記素、Unicode の補助コード ポイント、および補助平面の文字)。

    書記素は、1 つの基本文字と、その後に続く 1 つ以上の組み合わせ文字で表されます。 たとえば、文字 ä は Char オブジェクト (コード ポイント U+0061) とその後の Char オブジェクト (コード ポイント U+0308) によって表されます。

    と説明されているように、1文字がCharオブジェクト1つとは限りません。またIVSとサロゲートペアを挙げられていますが、それ以外にも引用したように書記素;graphemeもありますし、Unicodeとは? その歴史と進化、開発者向け基礎知識には1文字で38バイトにもなる絵文字が挙げられています。何をもって1文字とするかで大きく変わりますからどうしようもないかと思います。

    その上であえて挙げるならば、正規表現の文字クラスには \p{Cs} がサロゲート(U+D800~U+DFFF)を指しますのでこれを活用するぐらいでしょうか。

    2017年5月17日 12:59
  • 佐祐理さま

    コメントいただきありがとうございます。

    -------------------------------------------------------

    と説明されているように、1文字がCharオブジェクト1つとは限りません。またIVSとサロゲートペアを挙げられていますが、それ以外にも引用したように書記素;graphemeもありますし、Unicodeとは? その歴史と進化、開発者向け基礎知識には1文字で38バイトにもなる絵文字が挙げられています。何をもって1文字とするかで大きく変わりますからどうしようもないかと思います。

    ---------------------------------------------

    はい。Unicodeのすべてを理解しているわけではありませんが、非常に複雑な状態になっており、1文字1Charでない事は認識しております。

    そのうえで、Regex関連には、カスタマイズできるようなオプションは用意されていないのかなと思った次第です。

    私の感覚で言えば、見た目で1文字のものは「.」で検索の対象となってほしいというのが正直なところです。

    \p{Cs} は知りませんでした。これから活用方法を考えたいと思います。ありがとうございます。

    2017年5月18日 0:04