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

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

输出:orcpzsiayd

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


当前回答

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

的问候。

其他回答

从java.text.Normalizer开始。

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

这将从大多数字符中分离所有重音符号。然后,你只需要将每个字符与字母进行比较,并排除那些不是字母的字符。

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

如果你的文本是Unicode,你应该使用这个:

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

对于Unicode, \\P{M}匹配基本字形,\\P{M}(小写)匹配每个重音。

感谢GarretWilson提供的指针和正则表达式.info提供的Unicode指南。


需要注意的是,Normalizer本身不足以删除变音符。例如,下面的代码不会将重音的é替换为不重音的e:

import static java.text.Normalizer.normalize;
import static java.text.Normalizer.Form.*;

public class T {
  public static void main( final String[] args ) {
    final var text = "Brévis";

    System.out.println(
      normalize( text, NFD ) + " " + 
      normalize( text, NFC ) + " " + 
      normalize( text, NFKD ) + " " + 
      normalize( text, NFKC )
    );
  }
}

从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”之后按字母顺序排列。这是“条形强调”方法局限性的一个很好的例子。

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

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

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

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

如果你没有库,使用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。它不仅可以处理'Ł'和'Ø',而且还可以很好地从其他字母(如汉语)转录成拉丁字母。