将符号,口音字母转换为英文字母

问题是,如你所知, 在Unicode图表中有成千上万的字符,我想将所有相似的字符转换成英文字母。

比如这里有几个转换:

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

我看到有超过20个字母A / A的版本。 我不知道如何分类。 他们看起来像干草堆里的针。

unicode字符的完整列表在http://www.ssec.wisc.edu/~tomw/java/unicode.html或http://unicode.org/charts/charindex.html 。 只要尝试向下滚动,看看字母的变化。

我怎样才能转换所有这些与Java? 请帮帮我 :(

重新发布我的post如何从.NET中的string中删除变音符号(重音符号)?

这种方法在java中工作正常(纯粹是为了删除变音标记又名口音)

它基本上把所有的重音字符转换成deAccented的对应字符,然后再把它们的变音符合起来。 现在,您可以使用正则expression式来去除变音符号。

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

这是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/

试图“全部转化”是解决问题的错误方法。

首先,你需要了解你所要做的事情的局限性。 正如其他人所指出的,变音符号是有原因的:它们本质上是字母表中独特的字母,具有其自己的意义/声音等:去除这些标记就像replace英文单词中的随机字母一样。 这是之前,你甚至会考虑西里尔语言和其他基于脚本的文本,如阿拉伯文,根本不能被“转换”为英文。

如果你不论出于何种原因必须转换angular色,那么唯一明智的方法就是先把这个angular色缩小到手边。 考虑一下input的来源 – 如果你正在为“西方世界”编写一个应用程序(尽可能使用一个短语),那么你就不太可能需要parsing阿拉伯字符。 同样,Unicode字符集包含数百个math和graphics符号:用户没有(容易)直接input这些符号的方式,因此您可以假定它们可以被忽略。

通过采取这些合乎逻辑的步骤,可以减less可能的字符数量,以parsing到基于字典的查找/replace操作可行的点。 然后它成为创造词典的一小部分无聊的工作,并且执行replace的一个微不足道的任务。 如果你的语言支持原生的Unicode字符(正如Java所做的那样)并且正确地优化了静态结构,那么这样的查找和replace往往是非常快速的。

这来自于曾经在一个应用程序上工作的经验,这个应用程序允许最终用户search包含变音字符的书目数据。 查找数组(就像我们的情况一样)花了大概1个人的时间来制作,以涵盖所有西欧语言的所有变音符号。

由于将“家庭”转换为“3”的编码是随机的,并且不遵循任何可以用所涉及的Unicode代码点的信息来解释的algorithm,所以没有通用的方法来解决这个algorithm。

你将需要build立Unicode字符到他们相似的拉丁字符的映射。 您可以通过一些智能机器学习代表Unicode代码点的实际字形来做到这一点。 但是我认为这样做的努力将比手动构build映射更大。 特别是如果你有大量的例子,你可以build立你的映射。

为了澄清:一些replace实际上可以通过Unicode数据解决(如其他答案所示),但有些字母与它们相似的拉丁字符没有任何合理的关联。

例子:

  • “ђ”(U + 0452 CYRILLIC小写字母DJE)与“d”比“h”更相关,但用来表示“h”。
  • “Ŧ”(U + 0166拉丁文大写字母T)与“T”(顾名思义)有些相关,但用来表示“F”。
  • “ค”(U + 0E04 THAI CHARACTER KHO KHWAI)根本与任何拉丁字符无关,在你的例子中用来表示“a”

原来的请求已经被回答了。

不过,我发布了下面的答案,可能正在寻找通用音译代码来将任何字符集转换为Java中的Latin / English。

音译的天真含义:在最终forms/目标字符集中的翻译string听起来像原始forms的string。 如果我们想要将任何字符集转换为拉丁文(英文字母),那么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; } 

您可以尝试使用unidecode ,它可以作为ruby gem和cpan上的perl模块使用 。 本质上,它是一个巨大的查找表,其中每个unicode代码点与一个ascii字符或string相关。

将任意Unicode“转换”为ASCII的问题是,字符的含义是与文化相关的。 例如,讲德语的人的“ß”应转换为“ss”,而讲英语的人则可能将其转换为“beta”。

除此之外,Unicode具有相同字形的多个代码点。

结果是要做到这一点的唯一方法是创build一个巨大的表,每个Unicode字符和您想要将其转换为ASCII字符。 您可以通过将具有重音的字符标准化为标准化formsKD来获取快捷方式,但是并非所有字符都归一化为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... } 

如果需要转换“òéışöç-> 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类。

在这里看到一个例子

有没有简单或一般的方法来做你想做的,因为这只是你的主观看法,这些字母看起来loke你想要转换的拉丁字母。 它们实际上是分开的字母,它们自己的名字和声音恰好相反,只是表面上看起来像一个拉丁字母。

如果你想要这种转换,你必须根据你认为非拉丁字母应该被转换成的拉丁字母来创build你自己的翻译表。

(如果你只想删除标注符号,在这个线程中有一些答案: 如何从.NET中的string中删除变音符(重音符号)?但是你描述了一个更一般的问题)

testing过的string:阿玛尼亚塞尚太阳城尼娜

testing:

  • 来自Apache Commons Lang3的输出:AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • ICU4j输出:AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • JUnidecode的输出:AAAAAAECEEEEIIIIDNOOOOOOUUUUUss(有问题和另一个问题 )
  • Unidecode输出:AAAAAAECEEEEIIIIDNOOOOOOUUUUYY

最后的select是最好的。

我迟到了,但今天面对这个问题后,我发现这个答案很好:

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

参考: https : //stackoverflow.com/a/16283863

下面的类是诀窍:

 org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter