问题描述
我知道这一点
public static String stripAccents(String s) {
s = Normalizer.normalize(s,Normalizer.Form.NFD);
s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]","");
return s;
}
但是它不是我想要的方式。它改变了文字感
stripAccents("йод,ëлка,wäre") //иод,елка,ware
我只想删除重音
stripAccents("café") //cafe
解决方法
仅针对急性口音
s = Normalizer.normalize(s,Normalizer.Form.NFD); // Decompose
s = s.replace("\u0301",""); // Combining acute accent (´)
s = Normalizer.normalize(s,Normalizer.Form.NFC); // Compose again
组成最短,通常用字体表现更好。
即使没有正则表达式,也可以删除零长度的重音符号。
对于意大利语cafè带有重音符号的坟墓,请使用\u0300
。
似乎最好将带有重音符号的特定重音字符集重新映射为纯字母:
public static String stripAccents(String s) {
if (null == s || s.isEmpty()) {
return s;
}
final String[] map = {
"ÁÉÍÓÚÝáéíóúý","AEIOUYaeiouy"
};
return s.chars()
.mapToObj(c -> (char)(map[0].indexOf(c) > -1 ? map[1].charAt(map[0].indexOf(c)) : c))
.collect(Collector.of(
StringBuilder::new,StringBuilder::append,StringBuilder::toString
));
}
// or using updated switch statement in JDK 12
public static String stripAcuteAccents(String s) {
if (null == s || s.isEmpty()) {
return s;
}
char[] raw = s.toCharArray();
for (int i = 0; i < raw.length; i++) {
raw[i] = switch(raw[i]) {
case 'Á' -> 'A'; case 'É' -> 'E'; case 'Í' -> 'I';
case 'Ó' -> 'O'; case 'Ú' -> 'U'; case 'Ý' -> 'Y';
case 'á' -> 'a'; case 'é' -> 'e'; case 'í' -> 'i';
case 'ó' -> 'o'; case 'ú' -> 'u'; case 'ý' -> 'y';
default -> raw[i];
};
}
return new String(raw);
}
基本测试:
String[] tests = {"café","Á Toi","ÁÉÍÓÚÝáéíóúý - bcdef"};
Arrays.stream(tests)
.forEach(s -> System.out.printf("%s -> %s%n",s,stripAccents(s)));
输出
café -> cafe
Á Toi -> A Toi
ÁÉÍÓÚÝáéíóúý - bcdef -> AEIOUYaeiouy - bcdef