出于某种原因,这段 Java 代码给出了重叠匹配:
Pattern pat = Pattern.compile("(" + leftContext + ")" + ".*" + "(" + rightContext + ")", Pattern.DOTALL);
有什么方法/选项可以避免检测重叠?例如 leftContext rightContext rightContext 应该是 1 场比赛而不是 2 场
完整代码如下:
public static String replaceWithContext(String input, String leftContext, String rightContext, String newString){
Pattern pat = Pattern.compile("(" + leftContext + ")" + ".*" + "(" + rightContext + ")", Pattern.DOTALL);
Matcher matcher = pat.matcher(input);
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(buffer, "");
buffer.append(matcher.group(1) + newString + matcher.group(2));
}
matcher.appendTail(buffer);
return buffer.toString();
}
所以这是使用否定前瞻的最终答案,我没有意识到 * 是贪婪的:
Pattern pat = Pattern.compile("(" +
leftContext + ")" + "(?:(?!" +
rightContext + ").)*" + "(" +
rightContext + ")", Pattern.DOTALL);
最佳答案
您对“重叠”一词的使用令人困惑。显然,您的意思是正则表达式过于贪婪,匹配从第一个 leftContext
到最后一个 rightContext
的所有内容。您似乎已经想到了这一点——并且还提出了一种更好的方法——但至少仍然存在一个潜在问题。
你说 leftContext
和 rightContext
是“纯字符串”,我假设你的意思是它们不应该被解释为正则表达式,但它们会被解释。您需要对它们进行转义,否则它们包含的任何正则表达式元字符将导致不正确的结果或运行时异常。替换字符串也是如此,尽管只有 $
和反斜杠在那里具有特殊含义。这是一个示例(请注意非贪婪的 .*?
):
public static String replaceWithContext(String input, String leftContext, String rightContext, String newString){
String lcRegex = Pattern.quote(leftContext);
String rcRegex = Pattern.quote(rightContext);
String replace = Matcher.quoteReplacment(newString);
Pattern pat = Pattern.compile("(" + lcRegex + ").*?(" + rcRegex + ")", Pattern.DOTALL);
另一件事:如果您不对匹配的文本进行任何匹配后处理,您可以使用 replaceAll
而不是使用 appendReplacement
和 附加尾部
:
return input.replaceAll("(?s)(" + lcRegex + ")" +
"(?:(?!" + rcRegex + ").)*" +
"(" + rcRegex + ")",
"$1" + replace + "$2");
关于java - 避免在 Java 中重叠正则表达式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4290714/