java - 避免在 Java 中重叠正则表达式匹配

标签 java regex matcher

出于某种原因,这段 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 的所有内容。您似乎已经想到了这一点——并且还提出了一种更好的方法——但至少仍然存在一个潜在问题。

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

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/

相关文章:

java - 不同版本的客户端,在单一版本的 Kafka 代理上

java - 正则表达式代替 String.contains(xyz) (Java 1.7)

java - Matcher.appendEvaluated() 上出现 NullPointerException?

java - Crypto JS AES-128 密码 - 等效的 Javascript 代码

java - 为什么 `test2()` 方法编译成功,但 `test1()` 方法编译失败?

python - 仅当前面至少有 x 位数字时才获取数字选择

r - 从完整路径中仅提取文件名之前的文件夹名称

regex - 将正则表达式传递给 perl 子程序

Java string.matches() 返回错误语句

java - 实现带有偏移量的数组以减少数组长度