web-dev-qa-db-ja.com

Javaで印刷できないUnicode文字を置き換えるにはどうすればよいですか?

以下は、ASCII制御文字([\x00-\x1F\x7F]の省略形)を置き換えます。

my_string.replaceAll("\\p{Cntrl}", "?");

以下は、アクセント付き文字を含むすべてのASCII非印刷可能文字([\p{Graph}\x20]の省略形)を置き換えます。

my_string.replaceAll("[^\\p{Print}]", "?");

ただし、どちらもUnicode文字列には機能しません。 Unicode文字列から印刷できない文字を削除する良い方法はありますか?

75
dagnelies
my_string.replaceAll("\\p{C}", "?");

nicode regex の詳細を参照してください。 Java.util.regexPattern/String.replaceAllはそれらをサポートします。

122
Op De Cirkel

Op De Cirkelはほとんど正しいです。彼の提案はほとんどの場合うまくいきます:

myString.replaceAll("\\p{C}", "?");

ただし、myStringに非BMPコードポイントが含まれる場合は、より複雑になります。 \p{C}には、\p{Cs}のサロゲートコードポイントが含まれます。上記の置換方法は、サロゲートペアの半分のみを置換することにより、非BMPコードポイントを破損します。これは、意図した動作ではなく、Javaバグである可能性があります。

他の構成カテゴリの使用はオプションです。

myString.replaceAll("[\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}]", "?");

ただし、ペアの一部ではない単独の代理文字(各代理文字にはコードポイントが割り当てられています)は削除されません。非正規表現のアプローチは、\p{C}を適切に処理する唯一の方法です。

StringBuilder newString = new StringBuilder(myString.length());
for (int offset = 0; offset < myString.length();)
{
    int codePoint = myString.codePointAt(offset);
    offset += Character.charCount(codePoint);

    // Replace invisible control characters and unused code points
    switch (Character.getType(codePoint))
    {
        case Character.CONTROL:     // \p{Cc}
        case Character.FORMAT:      // \p{Cf}
        case Character.PRIVATE_USE: // \p{Co}
        case Character.SURROGATE:   // \p{Cs}
        case Character.UNASSIGNED:  // \p{Cn}
            newString.append('?');
            break;
        default:
            newString.append(Character.toChars(codePoint));
            break;
    }
}
51
noackjr

nicodeカテゴリ"その他、コントロール" およびpossibly「その他、フォーマット」 (残念ながら後者には印刷できない文字と印刷可能な文字の両方が含まれているようです)。

Java正規表現では、それぞれ\p{Cc}および\p{Cf}を使用してそれらを確認できます。

7
Joachim Sauer

あなたの目標のための打撃の方法

public static String removeNonAscii(String str)
{
    return str.replaceAll("[^\\x00-\\x7F]", "");
}

public static String removeNonPrintable(String str) // All Control Char
{
    return str.replaceAll("[\\p{C}]", "");
}

public static String removeSomeControlChar(String str) // Some Control Char
{
    return str.replaceAll("[\\p{Cntrl}\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}]", "");
}

public static String removeFullControlChar(String str)
{
    return removeNonPrintable(str).replaceAll("[\\r\\n\\t]", "");
} 
4
Ali Bagheri

私はそれを置き換えるのではなく、以下のような印刷できない文字を削除することを提案します

private String removeNonBMPCharacters(final String input) {
    StringBuilder strBuilder = new StringBuilder();
    input.codePoints().forEach((i) -> {
        if (Character.isSupplementaryCodePoint(i)) {
            strBuilder.append("?");
        } else {
            strBuilder.append(Character.toChars(i));
        }
    });
    return strBuilder.toString();
}
0
Ramesh Bathini

このためにこの単純な関数を使用しました:

private static Pattern pattern = Pattern.compile("[^ -~]");
private static String cleanTheText(String text) {
    Matcher matcher = pattern.matcher(text);
    if ( matcher.find() ) {
        text = text.replace(matcher.group(0), "");
    }
    return text;
}

これが役立つことを願っています。

0
user1300830

Op De Cirkelおよびnoackjrの回答に基づいて、次は一般的な文字列のクリーニングのために行うことです。1.先頭または末尾の空白のトリミング、2。dos2unix、3 mac2unix、4。空白を除くすべての「見えないUnicode文字」を削除します。

myString.trim.replaceAll("\r\n", "\n").replaceAll("\r", "\n").replaceAll("[\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}&&[^\\s]]", "")

Scala REPLでテスト済み。

0
RyanLeiTaiwan