匹配 lookbehind/ahead 多次

Matches lookbehind / ahead multiple times

代码:

public static void main(String[] args) {
    String mainTag = "HI";
    String replaceTag = "667";
    String text = "92<HI=/><z==//HIb><cHIhi> ";
    System.out.println(strFormatted(mainTag, replaceTag, text));

    mainTag = "aBc";
    replaceTag = "923";
    text = "<dont replacethis>abcabc< abcabcde >";
    System.out.println(strFormatted(mainTag, replaceTag, text));
}

private static String strFormatted(String mainTag, String replaceTag, String text) {
    return text.replaceAll("(?i)(?<=<)" + mainTag + "(?=.*>)", replaceTag);
}

所以,我想将 mainTag(变量)替换为 replaceTag(变量) 标签内(<...>)。

在上面的示例中,我想将 inside <...> 中所有出现的 mainTag HI(不区分大小写)替换为 667,但我的代码只替换了第一次出现的地方。

示例:

92<HI=/><z==//HIb><cHIhi> 

预期输出:

92<667=/><z==//667b><c667667> 

(mainTag = "HI", replaceTag = "667")

<dont replacethis>abcabc<abcabcde>

预期输出:

<dont replacethis>abcabc<923923de>

(mainTag = "aBc", replaceTag = "923");

注意:我的代码是错误的,不仅因为他只替换了1次,还因为只有"mainTag"在“<”之后才有效,在换句话说,lookbehind 仅适用于特定情况。

你只需要在这里向前看。这个想法是找到所有 mainTags,后面跟一个 >,然后匹配成对的 <>,并用 replaceTag 替换。以下正则表达式可以工作:

text.replaceAll("(?i)" + mainTag + "(?=[^<>]*>(?:[^<>]*<[^<>]*>)*[^<>]*)$", replaceTag);

解释:

(?i)               # Ignore Case
mainTag            # Match mainTag
(?=                # which is followed by
    [^<>]*         # Some 0 or more characters which are not < or >
    >              # Close the bracket (this ensures, mainTag is between closing bracket
    (?:            # Start a group (to match pair of bracket)
        [^<>]*     # non-bracket characters
        <          # Start a bracket 
        [^<>]*     # non-bracket characters
        >          # End the bracket
    )*             # Match the pair 0 or more times.
    [^<>]*         # Non-bracket characters 0 or more times.
)
[^<>]*)$

上面的正则表达式实际上假设括号总是平衡的。对于不平衡的正则表达式,这可能会产生意想不到的结果。但是正则表达式并不是真正适合这种工作的工具。

否则一个简单的正则表达式也可以正常工作:

"(?i)" + mainTag + "(?=[^<>]*>)"

这取决于您的用例。这不用担心平衡括号。你可以先试试第二种,如果适合所有场景,那就最好了。