2013-12-10 6 views
8

問題の文字列には、補完的なUnicode文字「\ ud84c \ udfb4」があります。 javadocによると、正規表現のマッチングは文字レベルではなくコードポイントレベルで行う必要があります。ただし、以下の分割コードでは、非サロゲート(\ udfb4)を非単語文字として扱い、分割しています。Java 7、正規表現と補足的なUnicode文字

何か不足していますか?単語以外の文字を分割するための他の選択肢は何ですか? (Java版 "1.7.0_07")

ありがとうございます。

Pattern non_word_regex = Pattern.compile("[\\W]", Pattern.UNICODE_CHARACTER_CLASS); 
String a = "\u529f\u80fd\u0020\u7d76\ud84c\udfb4\u986f\u793a\u5ee3\u544a"; 
String b ="功能 絶顯示廣告"; 
System.out.print("original "+a+"\norginal hex "); 
for(char c : a.toCharArray()){ 
    System.out.print(Integer.toHexString((int)c)); 
    System.out.print(' '); 
} 
System.out.println(); 

String[] tokens = non_word_regex.split(a); 

for(int i =0; i< tokens.length; i++){ 
    String token = tokens[i]; 
    System.out.print(i+" "); 
    for(char c : token.toCharArray()){ 
     System.out.print(Integer.toHexString((int)c)); 
     System.out.print(' '); 
    } 
    System.out.println(); 
} 

出力:
元の功能絶顯示廣告
orginalヘクス529f 80fd 20 7d76 d84c dfb4 986f 793a 5ee3 544A
0 529f 80fd
1 7d76 d84c
2 986f 793a 5ee3 544A

答えて

9

これは単純に正規表現エンジンのバグのようです。 \w式を使用すると、すべてが正しく一致し、2つの文字で構成された単一のコードポイントになります。これは、次のコードを実行すると簡単に確認できます。

Pattern pattern = Pattern.compile("(?U)[\\w]"); 
String str = "功能 絶顯示廣告"; 

Matcher matcher = pattern.matcher(str); 
while (matcher.find()) { 
    System.out.println(matcher.toMatchResult().group()); 
} 

私はちょうどスルー調査を行ったので、どこに問題があるのか​​を教えてください。方法compile()java.util.regex.Pattern(行1625から始まる)に見ると、正規表現をスキャンして補助文字をスキャンし、それらをスキャンでサポートするかどうかを決定するコードが表示されます。

このアプローチの問題点は、正規表現に補助文字がなくても、あなたの場合に起こるように、補完文字がまだ一致している可能性があるということです。 。

ソリューションが補助文字が含まれているいくつかの正規表現を工夫することであるが、彼らはマッチング処理には影響を与えません。

Pattern nonWordRegex = Pattern.compile("(?U)(?!\uDB80\uDC00)[\\W]"); 

一部(?!\uDB80\uDC00)は、トリックを行います。私はあなたがこのような無実のものを使用することをお勧め。これは、補助文字のプライベートな範囲の文字のための否定的な先読みです。つまり、テキスト内で見つからない可能性が最も高いことを意味します。とボイルラ:正規表現のエンジンは、パターンに補足的な文字があると考えて、彼らのサポートをオンにする!

+0

残念ながら、Matcherは単語境界を保存しません。 "[^ \ w]"を予測して使用すると、 "[\\ W]"と同じ結果が得られます。 – user3088039

+1

@ user3088039私はちょうどその問題を解決しました!答えをもう一度チェックして、私はそれを更新しました。 – Malcolm

+0

あなたは "(?U)"が補助キャラクターのサポートを有効にすると思います。カバーの下を見ていただきありがとうございます。それは美しく動作します。 – user3088039