避免在Java中重复正则表达式匹配
出于某种原因,这段Java代码为我提供了重叠匹配:避免在Java中重复正则表达式匹配,java,regex,matcher,Java,Regex,Matcher,出于某种原因,这段Java代码为我提供了重叠匹配: Pattern pat = Pattern.compile("(" + leftContext + ")" + ".*" + "(" + rightContext + ")", Pattern.DOTALL); 是否有任何方法/选项可以避免检测重叠?例如 leftContext rightContext rightContext 应该是1个匹配项而不是2个匹配项 以下是完整的代码: public static String replaceWi
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 + ")$"
因此,如果rightContext
不是最后一件事,您的正则表达式将不匹配
接下来,您可以捕获rightContext
之后的所有内容:
"(" + leftContext + ")" + ".*" + "(" + rightContext + ")(.*)"
然后丢弃第三组中的所有匹配项
但是,因为我们不知道leftContext
和righcontext
到底是什么,也许你的问题就在它们里面。你对“重叠”这个词的使用令人困惑。显然,您的意思是正则表达式太贪婪了,匹配了从第一个leftContext
到最后一个righcontext
的所有内容。看起来你已经明白了这一点,并且想出了一个更好的方法,但至少还有一个潜在的问题
您说过leftContext
和rightContext
是“纯字符串”,我想您的意思是它们不应该被解释为正则表达式,但它们会被解释为正则表达式。您需要转义它们,否则它们包含的任何正则表达式元字符都将导致不正确的结果或运行时异常。替换字符串也是如此,尽管只有$
和反斜杠在这里有特殊含义。下面是一个示例(请注意非贪婪的*?
):
还有一件事:如果您没有对匹配的文本进行任何匹配后处理,您可以使用replaceAll
,而不是使用appendReplacement
和appendTail
滚动自己的文本:
return input.replaceAll("(?s)(" + lcRegex + ")" +
"(?:(?!" + rcRegex + ").)*" +
"(" + rcRegex + ")",
"$1" + replace + "$2");
你能告诉我们什么是leftContext和rightContext吗?给我们举一个失败匹配的例子。让正则表达式匹配器捕获重叠的东西通常是一件稍微棘手的事情,而不是默认情况下发生的事情。如果看不到模式的内容,很难说发生了什么。它基本上需要lookarounds让matcher对字符串的同一部分进行多次检查。您正在这样做吗?rightContext和leftContext是纯字符串,例如leftContext=“ab”rightContext=“cd”默认情况下,量词是贪婪的,您描述的正则表达式不会产生多个匹配项。你为什么不发布一个完整的例子呢?啊,就是这样,有没有可能我可以将*的默认行为更改为非贪婪?嗯,我不确定这在我的代码中会如何工作,我不能只丢弃部分输入字符串
return input.replaceAll("(?s)(" + lcRegex + ")" +
"(?:(?!" + rcRegex + ").)*" +
"(" + rcRegex + ")",
"$1" + replace + "$2");