1

我试图通过用<b>kw</b>usingreplaceAll()方法替换每个关键字来使搜索关键字在结果标题中加粗。还需要忽略关键字中的任何特殊字符以进行突出显示。这是我正在使用的代码,但它在第二遍中双重替换了粗体指令。我正在寻找一个优雅的正则表达式解决方案,因为我的替代方案变得太大而没有涵盖所有情况。例如,使用此输入:

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;
}
4

3 回答 3

1

由于您已经从关键字中排除了特殊字符,因此最简单的解决方法可能就是在您的搜索模式中添加更多内容。以下内容应该会阻止您匹配已经是 html 标记一部分的文本:

highlighted = highlighted.replaceAll("(?i)[^<](" + token + ")", "<b>$1</b>");
于 2013-09-27T02:08:36.747 回答
1
  1. 不要忘记使用Pattern.quote(token) (除非保证非正则表达式转义kw
  2. 如果您一定要使用replaceAll()(而不是将输入标记化tag|text|tag|text|...并仅对文本应用替换,这将更加简单和快捷) - 下面的代码应该会有所帮助

请注意,它效率不高 - 它匹配一些空的或已经突出显示的点,因此需要在替换后“固化”,但应该CDATA正确处理 XML/HTML 标记(除了 )。

这是一个“固化”功能(无空检查):

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"));
于 2013-09-27T05:04:32.970 回答
1

这段代码对我有用,使用正则表达式lookbehind进行了最少的更改

highlighted = highlighted.replaceAll("(?i)((?<!<)(?<!/)" + token + "(?<!>))", "<b>$1</b>");
于 2013-09-27T18:53:06.573 回答