匹配 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 + "(?=[^<>]*>)"
这取决于您的用例。这不用担心平衡括号。你可以先试试第二种,如果适合所有场景,那就最好了。
代码:
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 + "(?=[^<>]*>)"
这取决于您的用例。这不用担心平衡括号。你可以先试试第二种,如果适合所有场景,那就最好了。