web-dev-qa-db-ja.com

記号、アクセント文字を英語のアルファベットに変換する

問題は、ご存知のように、数千の文字があります nicodeチャートでは であり、すべての同様の文字を英語のアルファベットの文字に変換したいということです。

例えば、ここにいくつかの変換があります:

ҥ->H
Ѷ->V
Ȳ->Y
Ǭ->O
Ƈ->C
tђє Ŧค๓เℓy --> the Family
...

そして、A/aには20以上のバージョンがあることがわかりました。そしてそれらを分類する方法がわかりません。彼らは干し草の山の針のように見えます。

Unicode文字の完全なリストは http://www.ssec.wisc.edu/~tomw/Java/unicode.html または http://unicode.org/charts/ charindex.html 。下にスクロールして、文字のバリエーションを確認してください。

これらをすべてJavaで変換するにはどうすればよいですか?私を助けてください :(

124
AhmetB - Google

。NETの文字列から発音区別符号(アクセント)を削除する方法は? から投稿を再投稿する

このメソッドは、Java(アクセント記号としての発音区別記号を削除する目的でのみ)で正常に機能します。

基本的に、アクセント記号付きのすべての文字を対応するdeAccentedに変換し、発音区別記号を結合します。これで、正規表現を使用して発音区別符号を取り除くことができます。

import Java.text.Normalizer;
import Java.util.regex.Pattern;

public String deAccent(String str) {
    String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD); 
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    return pattern.matcher(nfdNormalizedString).replaceAll("");
}
192
hashable

Apache Commons Lang の一部です。 3.0。

org.Apache.commons.lang3.StringUtils.stripAccents("Añ");

Anを返します

http://www.drillio.com/en/software-development/Java/removing-accents-diacritics-in-any-language/ も参照してください

71
Ondra Žižka

「それらすべてを変換する」ことは、問題に対する間違ったアプローチです。

まず、あなたがやろうとしていることの限界を理解する必要があります。他の人が指摘したように、発音区別記号は理由があります:それらは本質的にその言語のアルファベットの独自の意味/音などを持つユニークな文字です:これらのマークを削除することは英語の単語のランダムな文字を置き換えるのと同じです。これは、キリル言語やアラビア語などのスクリプトベースのテキストを検討する前です。これらのテキストは、単に英語に「変換」することはできません。

mustの場合、何らかの理由で文字を変換します。これにアプローチする唯一の賢明な方法は、まず手元のタスクの範囲を縮小します。入力のソースを検討してください-アプリケーションを「西洋の世界」にコーディングしている場合(他のフレーズと同じように適切なフレーズを使用するため)、アラビア語の文字を解析する必要はほとんどありません。同様に、Unicode文字セットには数百個の数学記号と絵記号が含まれています。ユーザーがこれらを直接入力する(簡単な)方法はないため、無視してもかまいません。

これらの論理的な手順を実行することで、解析可能な文字数を減らして、辞書ベースのルックアップ/置換操作が実行可能なポイントまで減らすことができます。その後、辞書を作成するわずかに退屈な作業と、置換を実行する簡単なタスクになります。ご使用の言語が(Javaがサポートするように)ネイティブUnicode文字をサポートし、静的構造を正しく最適化する場合、そのような検索と置換は目もくらむほど速い傾向があります。

これは、発音区別記号文字を含む書誌データをエンドユーザーが検索できるようにするために必要なアプリケーションで作業した経験から来ています。ルックアップ配列(この場合のように)は、すべての西ヨーロッパ言語のすべての発音区別符をカバーするために、おそらく1人日かかりました。

19
Ian

「ファミリー」を「tђєŦค๓เℓy」に変えるエンコーディングは事実上ランダムであり、関連するUnicodeコードポイントの情報で説明できるアルゴリズムに従わないため、このアルゴリズムを解決する一般的な方法はありません。

Unicode文字を類似したラテン文字にマッピングする必要があります。 Unicodeコードポイントを表す実際のグリフでスマートマシンラーニングを使用してこれを行うことができます。しかし、このための努力は、そのマッピングを手動で構築するよりも大きいと思います。特に、マッピングを作成できるサンプルが大量にある場合。

明確にするために:いくつかの置換はUnicodeデータを介して実際に解決できます(他の回答が示すように)が、一部の文字は単に似ているラテン文字との合理的な関連性がありません。

例:

  • 「ђ」(U + 0452キリル小文字DJE)は「h」よりも「d」に関連していますが、「h」を表すために使用されます。
  • 「Ŧ」(U + 0166ローマ字大文字Tストローク付き)は「T」(名前が示すとおり)に多少関連していますが、「F」を表すために使用されます。
  • 「ค」(U + 0E04 THAI CHARACTER KHO KHWAI)はラテン文字とはまったく関係がなく、例では「a」を表すために使用されます
16
Joachim Sauer

元の要求は既に回答済みです。

ただし、Javaで任意の文字セットをラテン語/英語に音訳するための一般的な音訳コードを探しているかもしれない人のために、以下の回答を投稿しています。

文字変換の素朴な意味:最終形式の翻訳された文字列/ターゲット文字セットは、元の形式の文字列のように聞こえます。文字セットをラテン語(英語のアルファベット)に音訳したい場合、ICU4(JavaのICU4Jライブラリー)が仕事をします。

Javaのコードスニペットを次に示します。

    import com.ibm.icu.text.Transliterator; //ICU4J library import

    public static String TRANSLITERATE_ID = "NFD; Any-Latin; NFC";
    public static String NORMALIZE_ID = "NFD; [:Nonspacing Mark:] Remove; NFC";

    /**
    * Returns the transliterated string to convert any charset to latin.
    */
    public static String transliterate(String input) {
        Transliterator transliterator = Transliterator.getInstance(TRANSLITERATE_ID + "; " + NORMALIZE_ID);
        String result = transliterator.transliterate(input);
        return result;
    }
7
Dayanand Gowda

テストされた文字列:ÁâÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝß

テスト済み:

  • Apache Commons Lang からの出力:AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • ICU4j からの出力:AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • JUnidecode からの出力:AAAAAAECEEEEIIIIDNOOOOOOUUUUUss(Ýと別の問題 issue
  • nidecode からの出力:AAAAAAECEEEEIIIIDNOOOOOOUUUUUYUss

最後の選択肢が最良です。

7
cactuschibre

「òéışöç-> oeisoc」を変換する必要がある場合、これを出発点として使用できます。

public class AsciiUtils {
    private static final String PLAIN_ASCII =
      "AaEeIiOoUu"    // Grave
    + "AaEeIiOoUuYy"  // acute
    + "AaEeIiOoUuYy"  // circumflex
    + "AaOoNn"        // tilde
    + "AaEeIiOoUuYy"  // umlaut
    + "Aa"            // ring
    + "Cc"            // cedilla
    + "OoUu"          // double acute
    ;

    private static final String UNICODE =
     "\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9"             
    + "\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD" 
    + "\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" 
    + "\u00C3\u00E3\u00D5\u00F5\u00D1\u00F1"
    + "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF" 
    + "\u00C5\u00E5"                                                             
    + "\u00C7\u00E7" 
    + "\u0150\u0151\u0170\u0171" 
    ;

    // private constructor, can't be instanciated!
    private AsciiUtils() { }

    // remove accentued from a string and replace with ascii equivalent
    public static String convertNonAscii(String s) {
       if (s == null) return null;
       StringBuilder sb = new StringBuilder();
       int n = s.length();
       for (int i = 0; i < n; i++) {
          char c = s.charAt(i);
          int pos = UNICODE.indexOf(c);
          if (pos > -1){
              sb.append(PLAIN_ASCII.charAt(pos));
          }
          else {
              sb.append(c);
          }
       }
       return sb.toString();
    }

    public static void main(String args[]) {
       String s = 
         "The result : È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô,ç";
       System.out.println(AsciiUtils.convertNonAscii(s));
       // output : 
       // The result : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o,c
    }
}

JDK 1.6は、このタスクに使用できるJava.text.Normalizerクラスを提供します。

例を参照してください here

6
RealHowTo

任意のUnicodeをASCIIに「変換」する際の問題は、文字の意味が文化に依存することです。たとえば、ドイツ語を話す人の「ß」は「ss」に変換する必要がありますが、英語を話す人はおそらく「B」に変換します。

さらに、ユニコードには同じグリフに対して複数のコードポイントがあるという事実を追加します。

結論としては、これを行う唯一の方法は、各Unicode文字とそれを変換するASCII文字を含む大規模なテーブルを作成することです。アクセント付き文字を正規化フォームKDに正規化することでショートカットを作成できますが、すべての文字がASCIIに正規化されるわけではありません。さらに、Unicodeはグリフのどの部分が「アクセント」であるかを定義しません。

これを行うアプリからの小さな抜粋を次に示します。

switch (c)
{
    case 'A':
    case '\u00C0':  //  À LATIN CAPITAL LETTER A WITH Grave
    case '\u00C1':  //  Á LATIN CAPITAL LETTER A WITH ACUTE
    case '\u00C2':  //  Â LATIN CAPITAL LETTER A WITH CIRCUMFLEX
    // and so on for about 20 lines...
        return "A";
        break;

    case '\u00C6'://  Æ LATIN CAPITAL LIGATURE AE
        return "AE";
        break;

    // And so on for pages...
}
4
Dour High Arch

これらの文字は、変換したいラテン文字のように見えるのは主観的な意見であるため、希望することを行う簡単な方法や一般的な方法はありません。それらは実際には、表面上はラテン文字のように見える独自の異なる名前と音を備えた別々の文字です。

その変換が必要な場合は、非ラテン文字を変換するラテン文字に基づいて独自の変換テーブルを作成する必要があります。

(発音区別記号のみを削除したい場合は、このスレッドにいくつかの回答があります: 。NETの文字列から発音区別符号(アクセント)を削除するにはどうすればよいですか? ただし、より一般的な問題を説明します)

4
JacquesB

unidecodeを使用してみてください。これは Ruby gem および Perlモジュールとして利用可能です。 cpan 。基本的に、巨大なルックアップテーブルとして機能し、各UnicodeコードポイントはASCII文字または文字列に関連付けられます。

4

私はパーティーに遅れましたが、今日この問題に直面した後、私はこの答えが非常に良いとわかりました:

String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
    .replaceAll("[^\\p{ASCII}]", "");

リファレンス: https://stackoverflow.com/a/1628386

4

次のクラスがトリックを行います:

org.Apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter
2
TomWolk