Java regex replaceAll with exclude pattern

时间:2013-09-27 00:31:52

标签: java regex replaceall

我正在尝试使用<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;
}

3 个答案:

答案 0 :(得分:1)

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

highlighted = highlighted.replaceAll("(?i)[^<](" + token + ")", "<b>$1</b>");

答案 1 :(得分:1)

  1. 不要忘记使用Pattern.quote(token)(除非保证非正则表达式转义kw
  2. 如果您必须使用replaceAll()(而不是将输入标记为tag|text|tag|text|...并仅将替换应用于文本,这将更加简单和快速) - 以下代码应该有帮助
  3. 请注意,它效率不高 - 它匹配一些空的或已经突出显示的点,因此在替换后需要“固化”,但应该正确处理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>");