programing

억양을 없애고 문자열 전체를 일반 문자로 변환할 수 있는 방법이 있나요?

prostudy 2022. 7. 16. 13:50
반응형

억양을 없애고 문자열 전체를 일반 문자로 변환할 수 있는 방법이 있나요?

으로 하는 으로는 사투리를 사용하는 방법 외에 방법이 요?String.replaceAll()한 글자씩 바꾸는 방법을 알려주세요.§:

력::orčpžsíáýd

★★★★★orcpzsiayd

러시아어 알파벳이나 중국어처럼 악센트가 있는 모든 글자를 포함할 필요는 없습니다.

당신을 위해 이 일을 처리하는 데 사용하세요.

string = Normalizer.normalize(string, Normalizer.Form.NFD);
// or Normalizer.Form.NFKD for a more "compatible" deconstruction 

이렇게 하면 모든 악센트 표시가 문자에서 분리됩니다.그리고 각 글자를 글자와 비교해서 글자가 아닌 글자는 버리면 됩니다.

string = string.replaceAll("[^\\p{ASCII}]", "");

텍스트가 유니코드일 경우 대신 다음을 사용해야 합니다.

string = string.replaceAll("\\p{M}", "");

Unicode의 ,\\P{M} 및 「」와 합니다.\\p{M}을 사용하다

포인터를 제공해 주신 GarretWilson과 훌륭한 Unicode 가이드를 제공해 주신 regular-expressions.info에 감사드립니다.

2011년부터 Apache Commons StringUtils.stripAccents(입력)(3.0 이후):

    String input = StringUtils.stripAccents("Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ");
    System.out.println(input);
    // Prints "This is a funky String"

주의:

승인된 답변(Erick Robertson의 답변)은 ø 또는 ł에 적용되지 않습니다.Apache Commons 3.5는 ø에서도 사용할 수 없지만 ł에서는 사용할 수 있습니다.Wikipedia의 , 기사를 읽은 후 "O"로 대체해야 할지 잘 모르겠습니다. "z" 뒤에 알파벳으로 구분된 노르웨이어와 덴마크어로 된 별도의 문자입니다.이는 "스트립 엑센트" 접근법의 한계를 보여주는 좋은 예입니다.

@virgo47의 솔루션은 매우 빠르지만 대략적입니다.승인된 답변은 Normalizer와 정규 표현을 사용합니다.비 ASC를 모두 삭제했기 때문에 정규 표현과 비교하여 정규 표현에 걸리는 시간은 어느 정도인지 궁금했습니다.II 문자는 정규식 없이 사용할 수 있습니다.

import java.text.Normalizer;

public class Strip {
    public static String flattenToAscii(String string) {
        StringBuilder sb = new StringBuilder(string.length());
        string = Normalizer.normalize(string, Normalizer.Form.NFD);
        for (char c : string.toCharArray()) {
            if (c <= '\u007F') sb.append(c);
        }
        return sb.toString();
    }
}

CharArray()를 호출하지 않고 char[]에 쓰는 것으로, 약간의 속도 향상을 얻을 수 있습니다.다만, 코드의 선명도가 저하하는 것이 적절한지는 잘 모르겠습니다.

public static String flattenToAscii(String string) {
    char[] out = new char[string.length()];
    string = Normalizer.normalize(string, Normalizer.Form.NFD);
    int j = 0;
    for (int i = 0, n = string.length(); i < n; ++i) {
        char c = string.charAt(i);
        if (c <= '\u007F') out[j++] = c;
    }
    return new String(out);
}

이 변동은 Normalizer를 사용하는 것이 정확하고 테이블을 사용하는 것이 속도라는 장점이 있습니다.제 머신에서는, 이 응답은, @virgo47의 응답보다 약 4배 빠르고, @virgo47의 응답보다 약 6.6~7배 느립니다(제 머신에서는 @virgo47의 응답보다 약 26배 느림).

편집: Java <6에 얽매이지 않고 속도가 중요하지 않거나 번역 테이블이 너무 제한적일 경우 David의 답변을 사용하십시오.는 '우리'를 사용하는 입니다.Normalizer(Java 6 서 (에 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 、 [ Java 6 ( Java 6 ) ]

이것은 「완벽한」솔루션은 아니지만, 범위(여기서는 Latin1,2)를 알고, Java 6 이전에 동작하고(실제 문제는 아니지만), 가장 추천하는 버전(문제가 될 수도 있고 아닐 수도 있음)보다 훨씬 빠릅니다.

    /**
 * Mirror of the unicode table from 00c0 to 017f without diacritics.
 */
private static final String tab00c0 = "AAAAAAACEEEEIIII" +
    "DNOOOOO\u00d7\u00d8UUUUYI\u00df" +
    "aaaaaaaceeeeiiii" +
    "\u00f0nooooo\u00f7\u00f8uuuuy\u00fey" +
    "AaAaAaCcCcCcCcDd" +
    "DdEeEeEeEeEeGgGg" +
    "GgGgHhHhIiIiIiIi" +
    "IiJjJjKkkLlLlLlL" +
    "lLlNnNnNnnNnOoOo" +
    "OoOoRrRrRrSsSsSs" +
    "SsTtTtTtUuUuUuUu" +
    "UuUuWwYyYZzZzZzF";

/**
 * Returns string without diacritics - 7 bit approximation.
 *
 * @param source string to convert
 * @return corresponding string without diacritics
 */
public static String removeDiacritic(String source) {
    char[] vysl = new char[source.length()];
    char one;
    for (int i = 0; i < source.length(); i++) {
        one = source.charAt(i);
        if (one >= '\u00c0' && one <= '\u017f') {
            one = tab00c0.charAt((int) one - '\u00c0');
        }
        vysl[i] = one;
    }
    return new String(vysl);
}

Tests on my HW with 32bit JDK show that this performs conversion from àèéľšťč89FDCC와 aeelstc89 연결노멀라이저 방식에서는 3.7초(37배 느림)로 FDC를 100만 회까지 연장할 수 있습니다.퍼포먼스에 대한 니즈가 있고 입력 범위를 알고 있는 경우, 이것은 고객 전용일 수 있습니다.

즐기세요 :-)

System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""));

날 위해 일했어위 스니펫의 출력은 제가 원하던 "aee"입니다만,

System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", ""));

대체를 하지 않았습니다.

언어에 따라서는, 악센트가 아니고(글자의 소리를 바꾸는) 발음이 다른 마크인 경우가 있습니다.

https://en.wikipedia.org/wiki/Diacritic#Languages_with_letters_containing_diacritics

"보시안어와 크로아티아어에는 각각 다른 문자로 간주되며 사전과 사전에서 알파벳 순서로 단어를 나열하는 문맥에 열거된 기호 ch, ich, d, and, ž가 있다."

그것들을 제거하는 것은 본래 단어의 의미를 바꾸는 것일 수도 있고, 글자를 완전히 다른 것으로 바꾸는 것일 수도 있다.

Strings Equality Check와 관련하여 동일한 문제에 직면한 적이 있는데, 비교 문자열 중 하나는 ASCII 문자 코드 128-255입니다.

즉, 비파괴 공간 - [16진수 - A0] 공간 [16진수 - 20].HTML 위에 Non-breaking space를 표시하기 위해 다음을 사용했습니다.그 문자와 그 바이트는

String s1 = "My Sample Space Data", s2 = "My Sample Space Data";
System.out.format("S1: %s\n", java.util.Arrays.toString(s1.getBytes()));
System.out.format("S2: %s\n", java.util.Arrays.toString(s2.getBytes()));

출력(바이트):

[ S1: [77, 121,32 83, 97, 109, 112, 108, 101, 10132 83, 112, 97, 99, 101,32, 68, 97, 116, 97] S2: [77, 121,-30, -128, -125 83, 97, 109, 112, 108, 101, 101-30, -128, -125 83, 112, 97, 99, 101,-30, -128, -125, 68, 97, 116, 97]

Different Spaces 및 해당 바이트 코드에 다음 코드를 사용합니다.

String spacing_entities = "very wide space,narrow space,regular space,invisible separator";
System.out.println("Space String :"+ spacing_entities);
byte[] byteArray = 
    // spacing_entities.getBytes( Charset.forName("UTF-8") );
    // Charset.forName("UTF-8").encode( s2 ).array();
    {-30, -128, -125, 44, -30, -128, -126, 44, 32, 44, -62, -96};
System.out.println("Bytes:"+ Arrays.toString( byteArray ) );
try {
    System.out.format("Bytes to String[%S] \n ", new String(byteArray, "UTF-8"));
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}
  • § Java용 Unicode 문자열의 ASCII 변환.unidecode

    String initials = Unidecode.decode( s2 );
    
  • § 사용 : Google Core.

    String replaceFrom = CharMatcher.WHITESPACE.replaceFrom( s2, " " );
    

    공간의 URL 인코딩에는 Guava library를 사용합니다.

    String encodedString = UrlEscapers.urlFragmentEscaper().escape(inputString);
    
  • 사용되었습니다String.replaceAll()와 함께.

    // \p{Z} or \p{Separator}: any kind of whitespace or invisible separator.
    s2 = s2.replaceAll("\\p{Zs}", " ");
    
    
    s2 = s2.replaceAll("[^\\p{ASCII}]", " ");
    s2 = s2.replaceAll(" ", " ");
    
  • § java.text 사용.노멀라이저Form. 이 열거형은 Unicode Standard Annex #15(Unicode 정규화 양식)에 설명된 4개의 Unicode 정규화 양식의 상수와 이에 액세스하는 두 가지 방법을 제공합니다.

    여기에 이미지 설명 입력

    s2 = Normalizer.normalize(s2, Normalizer.Form.NFKC);
    

Unidecode, Normalizer, StringUtils 등의 다양한 접근법으로 String 및 출력을 테스트합니다.

String strUni = "Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß";

// This is a funky String AE,O,D,ss
String initials = Unidecode.decode( strUni );

// Following Produce this o/p: Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß
String temp = Normalizer.normalize(strUni, Normalizer.Form.NFD);
Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
temp = pattern.matcher(temp).replaceAll("");

String input = org.apache.commons.lang3.StringUtils.stripAccents( strUni );

Unidecode를 사용하는 경우는, 이하에 나타내는 「My Code」(최종 코드)입니다.

public static void main(String[] args) {
    String s1 = "My Sample Space Data", s2 = "My Sample Space Data";
    String initials = Unidecode.decode( s2 );
    if( s1.equals(s2)) { //[ , ] %A0 - %2C - %20 « http://www.ascii-code.com/
        System.out.println("Equal Unicode Strings");
    } else if( s1.equals( initials ) ) {
        System.out.println("Equal Non Unicode Strings");
    } else {
        System.out.println("Not Equal");
    }

}

Junide code를 추천합니다.이것은 ' ''과 ','을 처리할 뿐만 아니라 중국어 등 다른 알파벳에서 라틴 알파벳으로 번역하는 데도 효과적입니다.

라이브러리가 없는 경우 regex 및 Normalizer를 사용하는 가장 좋은 방법 중 하나는 다음과 같습니다.

    public String flattenToAscii(String s) {
                if(s == null || s.trim().length() == 0)
                        return "";
                return Normalizer.normalize(s, Normalizer.Form.NFD).replaceAll("[\u0300-\u036F]", "");
}

이 방법은 replaceAll("[^\p{ASCII}]), "")보다 효율적이며 분음 부호가 필요하지 않은 경우(예시와 같이).

그렇지 않으면 p{ASC}를 사용해야 합니다.II} 패턴

안부 전해요.

@David Conrad 솔루션은 노멀라이저를 사용해 본 것 중 가장 빠릅니다만, 버그가 있습니다.기본적으로 액센트가 아닌 문자, 예를 들어 한자나 ᄋ와 같은 다른 글자는 모두 제거된다.제거하려는 문자는 공백이 없는 문자이며 마지막 문자열에서 추가 너비를 차지하지 않습니다.이 제로 폭의 문자는 기본적으로 다른 문자와 결합됩니다.예를 들어 '와 같이 하나의 문자로 고립되어 있는 것을 볼 수 있다면 공백 문자와 결합되어 있다고 생각합니다.

public static String flattenToAscii(String string) {
    char[] out = new char[string.length()];
    String norm = Normalizer.normalize(string, Normalizer.Form.NFD);

    int j = 0;
    for (int i = 0, n = norm.length(); i < n; ++i) {
        char c = norm.charAt(i);
        int type = Character.getType(c);

        //Log.d(TAG,""+c);
        //by Ricardo, modified the character check for accents, ref: http://stackoverflow.com/a/5697575/689223
        if (type != Character.NON_SPACING_MARK){
            out[j] = c;
            j++;
        }
    }
    //Log.d(TAG,"normalized string:"+norm+"/"+new String(out));
    return new String(out);
}

각 문자를 HEX로 변환하여 다른 HEX로 교체하는 것이 가장 좋은 해결책이라고 생각합니다.Unicode 타이핑이 2개 있기 때문입니다.

Composite Unicode
Precomposed Unicode

예를 들어 컴포지트 유니코드로 작성된 " by"은 사전 합성 유니코드로 작성된 "ồ"와 다릅니다.샘플 문자를 복사하여 변환하여 차이를 확인할 수 있습니다.

In Composite Unicode, "Ồ" is combined from 2 char: Ô (U+00d4) and ̀ (U+0300)
In Precomposed Unicode, "Ồ" is single char (U+1ED2)

이 기능은 일부 은행이 정보를 코어뱅크(통상 Unicode를 지원하지 않음)로 전송하기 전에 변환하기 위해 개발되었으며, 최종 사용자가 여러 Unicode 입력을 사용하여 데이터를 입력할 때 이 문제에 직면했습니다.따라서 HEX로 변환하여 교체하는 것이 가장 신뢰할 수 있는 방법이라고 생각합니다.

빠르고 안전한 방법

public static String removeDiacritics(String str) {
    if (str == null)
        return null;
    if (str.isEmpty())
        return "";
    
    int len = str.length();
    StringBuilder sb
        = new StringBuilder(len);
    
    //iterate string codepoints
    for (int i = 0; i < len; ) {
        int codePoint = str.codePointAt(i);
        int charCount
            = Character.charCount(codePoint);
        
        if (charCount > 1) {
            for (int j = 0; j < charCount; j++)
                sb.append(str.charAt(i + j));
            i += charCount;
            continue;
        }
        else if (codePoint <= 127) {
            sb.append((char)codePoint);
            i++;
            continue;
        }
        
        sb.append(
            java.text.Normalizer
                .normalize(
                    Character.toString((char)codePoint),
                    java.text.Normalizer.Form.NFD)
                        .charAt(0));
        i++;
    }
    
    return sb.toString();
}

이 솔루션은 이미 Maven Repository의 StringUtils.stripAccents()에서 사용 가능하며 @DavidS에서 설명한 바와 같이 mentioned에서 동작합니다.ø와 so 둘 다 작동해야 하기 때문에 아래와 같이 수정하였습니다.다른 사람들에게도 도움이 될 수 있다.

public static String stripAccents(final String input) {
    if (input == null) {
        return null;
    }
    final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD));
    for (int i = 0; i < decomposed.length(); i++) {
        if (decomposed.charAt(i) == '\u0141') {
            decomposed.setCharAt(i, 'L');
        } else if (decomposed.charAt(i) == '\u0142') {
            decomposed.setCharAt(i, 'l');
        }else if (decomposed.charAt(i) == '\u00D8') {
            decomposed.setCharAt(i, 'O');
        }else if (decomposed.charAt(i) == '\u00F8') {
            decomposed.setCharAt(i, 'o');
        }
    }
    // Note that this doesn't correctly remove ligatures...
    return Pattern.compile("\\p{InCombiningDiacriticalMarks}+").matcher(decomposed).replaceAll("");
}

입력 문자열Ł Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Ø ø
출력 문자열L This is a funky String O o

만약 누군가가 코틀린에서 이것을 하려고 애쓰고 있다면, 이 코드는 마법처럼 작동한다.모순을 피하기 위해 .toUpperCase와 Trim()도 사용합니다.그 후 다음 함수를 캐스팅합니다.

   fun stripAccents(s: String):String{

   if (s == null) {
      return "";
   }

val chars: CharArray = s.toCharArray()

var sb = StringBuilder(s)
var cont: Int = 0

while (chars.size > cont) {
    var c: kotlin.Char
    c = chars[cont]
    var c2:String = c.toString()
   //these are my needs, in case you need to convert other accents just Add new entries aqui
    c2 = c2.replace("Ã", "A")
    c2 = c2.replace("Õ", "O")
    c2 = c2.replace("Ç", "C")
    c2 = c2.replace("Á", "A")
    c2 = c2.replace("Ó", "O")
    c2 = c2.replace("Ê", "E")
    c2 = c2.replace("É", "E")
    c2 = c2.replace("Ú", "U")

    c = c2.single()
    sb.setCharAt(cont, c)
    cont++

}

return sb.toString()

}

이렇게 재미있는 캐스트를 할 수 있습니다.

     var str: String
     str = editText.text.toString() //get the text from EditText
     str = str.toUpperCase().trim()

     str = stripAccents(str) //call the function

언급URL : https://stackoverflow.com/questions/3322152/is-there-a-way-to-get-rid-of-accents-and-convert-a-whole-string-to-regular-lette

반응형