Java에서 인쇄 할 수없는 유니 코드 문자를 어떻게 바꿀 수 있습니까?


88

다음은 ASCII 제어 문자 (의 약어)를 대체합니다 [\x00-\x1F\x7F].

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

다음은 [\p{Graph}\x20]악센트 부호가있는 문자를 포함하여 인쇄 할 수없는 모든 ASCII 문자 (의 약어)를 대체합니다 .

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

그러나 유니 코드 문자열에는 둘 다 작동하지 않습니다. 누구든지 유니 코드 문자열에서 인쇄 할 수없는 문자를 제거하는 좋은 방법이 있습니까?


2
부록처럼 : 유니 코드 일반 범주 목록은 UAX # 44
McDowell 2011 년


1
@Stewart : 안녕하세요, 제목 외에 질문 / 답변을 보셨나요?!?
dagnelies

1
@Stewart : 다른 질문은 인쇄 할 수없는 문자의 ascii 하위 집합 만 다룹니다 !!!
dagnelies

답변:


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

유니 코드 정규식 에 대해 자세히 알아보세요 . java.util.regexPattern/ String.replaceAll그들을 지원합니다.


Java 1.6에서는 최소한 지원하지 않습니다. download.oracle.com/javase/6/docs/api/java/util/regex/… ... 나는 또한 당신의 라인을 시도해 보았고 백 슬래시를 놓친 것 외에도 분명히 작동하지 않습니다.
dagnelies

이것은 작동합니다 : char c = 0xFFFA; String.valueOf(c).replaceAll("\\p{C}", "?");또한 유니 코드 지원 섹션 의 패턴에 대한 javadoc 에서 카테고리를 지원한다고 말합니다
Op De Cirkel 2011 년

당신이 맞아요! 죄송합니다. Zl Zp 카테고리는 대부분 문제의 원인이 되었기 때문에 추가해야했기 때문에 알아 차리지 못했습니다. 완벽하게 작동합니다. 다시 투표 할 수 있도록 게시물을 약간 수정 해 주시겠습니까?
dagnelies 2011-06-01

6
\ p {Zs} 그룹의 일부인 보이지 않는 공백 문자 (예 : 0x0200B)도 있습니다. 불행히도 여기에는 일반 공백도 포함됩니다. 공백을 포함하지 않아야하는 입력 문자열을 필터링하려는 사람들을 위해 문자열 s.replaceAll("[\\p{C}\\p{Z}]", "")이 매력을 발휘합니다.
Andrey L

1
이것은 내가, 내가려고 무엇을 찾고 있었다입니다 replaceAll("[^\\u0000-\\uFFFF]", "")하지만 성공도 없었다
Bibaswann Bandyopadhyay을

58

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;
    }
}

8

당신은에 관심이있을 수 있습니다 유니 코드 범주 "기타, 제어"가능성 "기타, 형식" (불행하게도 후자는 모두 인쇄 할 수없는 및 인쇄 가능한 문자를 포함 할 것).

Java 정규식에서는 \p{Cc}\p{Cf}각각을 사용하여 확인할 수 있습니다 .


글쎄, 너무 나쁜 자바 표현식에는 그것들이 없지만 적어도 지금은 목록이 있습니다 ...없는 것보다 낫습니다. 감사
dagnelies

4

목표를위한 방법

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]", "");
} 

0

이 간단한 기능을 사용했습니다.

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

Op De Cirkelnoackjr 의 답변에 따라 일반적인 문자열 정리를 위해 다음과 같이합니다. 1. 선행 또는 후행 공백 제거, 2. dos2unix, 3. mac2unix, 4. 공백을 제외한 모든 "보이지 않는 유니 코드 문자"제거 :

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

Scala REPL로 테스트되었습니다.


0

대체 대신 아래와 같이 인쇄 할 수없는 문자를 제거 할 것을 제안합니다.

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();
}

-4

전화 번호 +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 );
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.