Następujące znaki zastąpią znaki sterujące ASCII (skrót [\x00-\x1F\x7F]
):
my_string.replaceAll("\\p{Cntrl}", "?");
Poniższe zastąpi wszystkie niedrukowalne znaki ASCII (skrót [\p{Graph}\x20]
), w tym znaki akcentowane:
my_string.replaceAll("[^\\p{Print}]", "?");
Jednak żaden z nich nie działa w przypadku ciągów Unicode. Czy ktoś ma dobry sposób na usunięcie niedrukowalnych znaków z ciągu znaków Unicode?
Odpowiedzi:
my_string.replaceAll("\\p{C}", "?");
Zobacz więcej o wyrażeniach regularnych Unicode .
java.util.regexPattern
/String.replaceAll
wspiera ich.źródło
char c = 0xFFFA; String.valueOf(c).replaceAll("\\p{C}", "?");
również w javadoc do wyszukiwania wzorców w sekcji obsługi Unicode , mówi, że obsługuje kategories.replaceAll("[\\p{C}\\p{Z}]", "")
spełni urokreplaceAll("[^\\u0000-\\uFFFF]", "")
ale nie udało mi sięOp De Cirkel ma w większości rację. Jego sugestia zadziała w większości przypadków:
Ale jeśli
myString
może zawierać punkty kodowe inne niż BMP, jest to bardziej skomplikowane.\p{C}
zawiera zastępcze punkty kodowe\p{Cs}
. Powyższa metoda zamiany spowoduje uszkodzenie punktów kodowych innych niż BMP, czasami zastępując tylko połowę pary zastępczej. Możliwe, że jest to błąd języka Java, a nie zamierzone zachowanie.Istnieje możliwość skorzystania z innych kategorii składników:
myString.replaceAll("[\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}]", "?");
Jednak pojedyncze znaki zastępcze niebędące częścią pary (każdy znak zastępczy ma przypisany punkt kodowy) nie zostaną usunięte. Podejście inne niż wyrażenia regularne to jedyny sposób, jaki znam, aby poprawnie obsługiwać
\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; } }
źródło
Możesz być zainteresowany kategoriami Unicode „Inne, sterowanie” i prawdopodobnie „Inny, format” (niestety ten drugi wydaje się zawierać zarówno znaki niedrukowalne, jak i drukowalne).
W wyrażeniach regularnych Java możesz je sprawdzić używając odpowiednio
\p{Cc}
i\p{Cf}
.źródło
metody dla Twojego celu
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]", ""); }
źródło
Użyłem do tego prostej funkcji:
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; }
Mam nadzieję, że to jest przydatne.
źródło
Opierając się na odpowiedziach Op De Cirkel i noackjr , wykonuję następujące czynności w celu ogólnego czyszczenia ciągów: 1. przycinanie wiodących lub końcowych białych znaków, 2. dos2unix, 3. mac2unix, 4. usuwanie wszystkich „niewidocznych znaków Unicode” z wyjątkiem białych znaków:
myString.trim.replaceAll("\r\n", "\n").replaceAll("\r", "\n").replaceAll("[\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}&&[^\\s]]", "")
Przetestowano za pomocą Scala REPL.
źródło
Proponuję usunąć niedrukowalne znaki, jak poniżej, zamiast je zastąpić
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(); }
źródło
Przeprojektowałem kod dla numerów telefonów +9 (987) 124124 Wyodrębniłem cyfry z ciągu znaków w Javie
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 ); }
źródło