Как я могу заменить непечатаемые символы Unicode в Java?
ниже будут заменены управляющие символы ASCII (сокращение для [x00-x1Fx7F]
):
my_string.replaceAll("p{Cntrl}", "?");
ниже будут заменены все символы ASCII непечатаемые (стенография для [p{Graph}x20]
), в том числе акцентированных символов:
my_string.replaceAll("[^p{Print}]", "?");
однако ни один из них не работает для строк Unicode. У кого-нибудь есть хороший способ удалить непечатаемые символы из строки unicode?
6 ответов:
my_string.replaceAll("\p{C}", "?");
подробнее о регулярных выражений в Unicode.
java.util.regexPattern
/String.replaceAll
поддерживает их.
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; } }
Вы можете быть заинтересованы в категории Юникода"Другое, Управление" и возможно"Другие", "Формат" (к сожалению, последний, кажется, содержит как непечатные, так и печатные символы).
в регулярных выражениях Java вы можете проверить их с помощью
\p{Cc}
и\p{Cf}
соответственно.
методы в ударе для вашей цели
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]", ""); }
я использовал эту простую функцию для этого:
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; }
надеюсь, что это полезно.
я переработал код для номера телефона +9 (987) 124124 извлечение цифр из строки в Java
public static String stripNonDigitsV2( CharSequence input ) { if (input == null) return null; if ( input.length() == 0 ) return ""; char[] result = new char[input.length()]; int cursor = 0; CharBuffer buffer = CharBuffer.wrap( input ); int i=0; while ( i< buffer.length() ) { //buffer.hasRemaining() char chr = buffer.get(i); if (chr=='u'){ i=i+5; chr=buffer.get(i); } if ( chr > 39 && chr < 58 ) result[cursor++] = chr; i=i+1; } return new String( result, 0, cursor ); }