我正在尝试使用<b>kw</b>
方法将每个关键字替换为replaceAll()
,从而使结果标题中的搜索关键字变为粗体。还需要忽略关键字中的任何特殊字符以突出显示。这是我正在使用的代码,但它在第二遍中替换了粗体指令。我正在寻找一个优雅的正则表达式解决方案,因为我的替代方案变得太大而没有覆盖所有情况。例如,使用此输入:
addHighLight("a b", "abacus")
...我得到了这个结果:
<<b>b</b>>a</<b>b</b>><b>b</b><<b>b</b>>a</<b>b</b>>cus
public static String addHighLight(String kw, String text) {
String highlighted = text;
if (kw != null && !kw.trim().isEmpty()) {
List<String> tokens = Arrays.asList(kw.split("[^\\p{L}\\p{N}]+"));
for(String token: tokens) {
try {
highlighted = highlighted.replaceAll("(?i)(" + token + ")", "<b>$1</b>");
} catch ( Exception e) {
e.printStackTrace();
}
}
}
return highlighted;
}
答案 0 :(得分:1)
由于您已经从关键字中排除了特殊字符,因此最简单的方法可能是为搜索模式添加更多内容。以下内容应该阻止您匹配已经属于html标记的文本:
highlighted = highlighted.replaceAll("(?i)[^<](" + token + ")", "<b>$1</b>");
答案 1 :(得分:1)
Pattern.quote(token)
(除非保证非正则表达式转义kw
)replaceAll()
(而不是将输入标记为tag|text|tag|text|...
并仅将替换应用于文本,这将更加简单和快速) - 以下代码应该有帮助请注意,它效率不高 - 它匹配一些空的或已经突出显示的点,因此在替换后需要“固化”,但应该正确处理XML / HTML标记(CDATA
除外)。
这是一个“固化”功能(无空检查):
private static Pattern cureDoubleB = Pattern.compile("<b><b>([^<>]*)</b></b>");
private static Pattern cureEmptyB = Pattern.compile("<b></b>");
private static String cure(String input) {
return cureEmptyB.matcher(cureDoubleB.matcher(input).replaceAll("<b>$1</b>")).replaceAll("");
}
以下是replaceAll行的外观:
String txt = "[^<>" + Pattern.quote(token.substring(0, 1).toLowerCase()) + Pattern.quote(token.substring(0, 1).toUpperCase()) +"]*";
highlighted = cure(highlighted.replaceAll("((<[^>]*>)*"+txt+")(((?i)" + Pattern.quote(token) + ")|("+txt+"))", "$1<b>$4</b>$5"));
答案 2 :(得分:1)
此代码适用于我,使用正则表达式lookbehind
进行最少的更改highlighted = highlighted.replaceAll("(?i)((?<!<)(?<!/)" + token + "(?<!>))", "<b>$1</b>");