除了使用String.replaceAll()方法并逐个替换字母之外,还有更好的方法来摆脱重音并使这些字母规则吗? 例子:

输入:或者čpžsíáýd

输出:orcpzsiayd

它不需要包括所有有口音的字母,比如俄语字母或汉语字母。


当前回答

我认为最好的解决方案是将每个char转换为HEX,并用另一个HEX替换它。因为有两种Unicode类型:

Composite Unicode
Precomposed Unicode

例如,Composite Unicode编写的“Ồ”不同于precompose Unicode编写的“Ồ”。您可以复制我的示例字符并转换它们以查看差异。

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

我为一些银行开发了这个功能,以便在将信息发送到核心银行(通常不支持Unicode)之前转换信息,当最终用户使用多种Unicode类型输入数据时,就会遇到这个问题。所以我认为,转换为HEX并替换它是最可靠的方法。

其他回答

因为这个解决方案已经在Maven资源库的stringutils . striptones()中可用,并且可以在@DavidS提到的Ł中使用。 但我需要这是工作在Ø和Ł所以修改如下。可能对其他人也有帮助。

更新


这是StringUtils的修改版本。stripaccent (String obj),它包含旧的功能,同时处理Ø和Ł字符。

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ĥïŝ 这是一个时髦的字符串O O

根据语言的不同,这些可能不被认为是重音(改变字母的发音),而是变音符符号

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

“波斯尼亚语和克罗地亚语都有符号“č”、“ovic”、“đ”、“š”和“ž”,这些符号被认为是单独的字母,在字典和其他按字母顺序排列单词的语境中都是这样列出的。”

删除它们可能会从本质上改变单词的意思,或者将字母变成完全不同的字母。

从2011年开始,你可以使用Apache Commons stringutils . stripaccent (input)(从3.0开始):

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

注意:

接受的答案(Erick Robertson的)对于Ø或Ł不适用。Apache Commons 3.5也不能用于Ø,但它可以用于Ł。在阅读了维基百科上关于Ø的文章后,我不确定它是否应该被“O”取代:它在挪威语和丹麦语中是一个单独的字母,在“z”之后按字母顺序排列。这是“条形强调”方法局限性的一个很好的例子。

如果你没有库,使用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{ASCII}模式。

的问候。

我推荐Junidecode。它不仅可以处理'Ł'和'Ø',而且还可以很好地从其他字母(如汉语)转录成拉丁字母。