4

出于某种原因,这段 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);
4

2 回答 2

2

您对“重叠”一词的使用令人困惑。显然,您的意思是正则表达式太贪婪,匹配从 firstleftContext到 last的所有内容rightContext。看来您已经发现了这一点——并且还提出了一种更好的方法——但仍然至少存在一个潜在问题。

您说leftContext并且rightContext是“纯字符串”,我假设您的意思是它们不应该被解释为正则表达式,但它们会。您需要对它们进行转义,否则它们包含的任何正则表达式元字符都会导致不正确的结果或运行时异常。您的替换字符串也是如此,尽管只有$反斜杠在此处具有特殊含义。这是一个示例(.*?也请注意 non-greedy ):

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);

另一件事:如果您没有对匹配的文本进行任何匹配后处理,则可以使用andreplaceAll代替滚动您自己的:appendReplacementappendTail

return input.replaceAll("(?s)(" + lcRegex + ")" +
                        "(?:(?!" + rcRegex + ").)*" +
                        "(" + rcRegex + ")",
    "$1" + replace + "$2");
于 2010-11-29T21:40:44.453 回答
1

可能性很小,这取决于您真正需要什么。

您可以$在正则表达式的末尾附加,如下所示:

"(" + leftContext + ")" + ".*" + "(" + rightContext + ")$"

所以如果rightContext不是最后一件事,你的正则表达式将不匹配。

接下来,您可以捕获之后的所有内容rightContext

"(" + leftContext + ")" + ".*" + "(" + rightContext + ")(.*)"

然后丢弃第三个匹配组中的所有内容。

但是,由于我们不知道究竟是什么leftContextrightContext也许你的问题在于它们。

于 2010-11-27T08:57:41.923 回答