web-dev-qa-db-ja.com

文書化されていないJava正規表現文字クラス:\ p {C}

Javaプロジェクト:"[\\p{C}&&\\S]"で興味深い正規表現を見つけました

&&は「交差点の設定」を意味し、\Sは「非空白」であることを理解していますが、\p{C}とは何であり、大丈夫ですか使用するには?

Java.util.regex.Pattern documentation は言及していません。リスト上の唯一の類似クラスは\p{Cntrl}ですが、動作は異なります。両方とも制御文字で一致しますが、\p{C}は上記のUnicode文字でtwiceと一致しますPILE OF POOなどのU + FFFF:

public class StrangePattern {
    public static void main(String[] argv) {

        // As far as I can tell, this is the simplest way to create a String
        // with code points above U+FFFF.
        String poo = new String(Character.toChars(0x1F4A9));

        System.out.println(poo);  // prints `????`
        System.out.println(poo.replaceAll("\\p{C}", "?"));  // prints `??`
        System.out.println(poo.replaceAll("\\p{Cntrl}", "?"));  // prints `????`
    }
}

私がどこでも見つけた唯一の言及は、 ここ です:

\ p {C}または\ p {Other}:目に見えない制御文字と未使用のコードポイント。

ただし、\p{Other}はJavaには存在しないようで、一致するコードポイントは使用されません。

My Javaバージョン情報:

$ Java -version
Java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

ボーナス質問:元のパターン、"[\\p{C}&&\\S]"の意図は何ですか?これは、メールで送信される前に文字列を検証するメソッドで発生します。そのパターンが一致すると、「Invalid string」というメッセージの例外が発生します。

27
doctaphred

Unicodeサポートの下のパターンドキュメントに埋もれていると、次のことがわかります。

このクラスは、レベル1の nicode技術標準#18:Unicode正規表現 、およびRL2.1 Canonical Equivalentsに準拠しています。

...

カテゴリはオプションの接頭辞Isで指定できます:\ p {L}と\ p {IsL}は両方ともUnicode文字のカテゴリを示します。スクリプトおよびブロックと同様に、general_category = Luまたはgc = Luのように、キーワードgeneral_category(またはその短縮形gc)を使用してカテゴリを指定することもできます。

サポートされているカテゴリは、Characterクラスで指定されたバージョンのUnicode標準のカテゴリです。カテゴリ名は、標準で定義されているもので、規範的および情報的です。

nicode Technical Standard#18 から、Cがその他のGeneral_Category値と一致するように定義されており、このサポートがレベル1準拠の要件の一部であることがわかります。 Javaは\p{C}を実装しています。これは、UTS#18のレベル1への準拠を主張しているためです。


おそらくshould\p{Other}をサポートする必要がありますが、明らかにサポートしていません。

さらに悪いことに、レベル1準拠に必要な RL1.7 に違反しているため、コード単位ではなくコードポイントで一致が発生する必要があります。

この要件を満たすために、実装は、U + FFFFからU + 10FFFFまでの値を含むUnicodeコードポイントの全範囲を処理する必要があります。 特に、UTF-16が使用される場合、先頭のサロゲートとそれに続く末尾のサロゲートで構成されるシーケンスは、一致する単一のコードポイントとして処理されます。

テスト文字列は、2つのサロゲートではなくGeneral_Category = So(その他の記号)を使用した単一の絵文字コードポイントとして一致する必要があるため、テスト文字列には\p{C}に一致するものはありません。

22
user2357112

https://regex101.com/ によると、\ p {C}は一致します

目に見えない制御文字と未使用のコードポイント

(Java文字列なので、文字列\\ p {C}は正規表現\ p {C}であるため、\をエスケープする必要があります))

\ p {C}はおそらく有効な(文字で埋められた)文字列内に表示されるべきではないため、これは「ハッキングされた文字列チェック」であると推測しますが、作成者はチェックしたものとチェックしたいものとしてコメントを残す必要があります通常は2つの異なるものです。

4
Tezra

有効な2文字のUnicodeカテゴリコードまたはUnicodeカテゴリコードを開始する1文字以外は、JavaはUnicodeカテゴリの1文字と2文字の略語のみをサポートするため、違法です。そのため_\p{Other}_はここでは機能しません。

_\p{C}_は、PILE OF POOなどの_U+FFFF_より上のUnicode文字でtwiceと一致します。

正しい。 JavaはUnicode文字に対して内部的にUTF-16エンコーディングを使用し、????はサロゲートペアと呼ばれる2つの16ビットコード単位(_0xD83D 0xDCA9_)としてエンコードされます( high surrogates )および_\p{C}_は各半分に個別に一致するため

_\p{Cs}_または_\p{Surrogate}_:UTF-16エンコードのサロゲートペアの半分。

結果セットに2つの一致が表示されます。

元のパターン_[\\p{C}&&\\S]_の意図は何ですか?

あまり正当な理由はわかりませんが、開発者はカテゴリOther(電子メールの件名でスパムを避ける goomojies など)の文字を心配しているようです。それら。

1
revo