Оп Де Сиркель в основном прав. Его предложение сработает в большинстве случаев:
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);
switch (Character.getType(codePoint))
{
case Character.CONTROL:
case Character.FORMAT:
case Character.PRIVATE_USE:
case Character.SURROGATE:
case Character.UNASSIGNED:
newString.append('?');
break;
default:
newString.append(Character.toChars(codePoint));
break;
}
}