Java正则表达式 - 重叠匹配

Evg*_*eny 20 java regex

在以下代码中:

public static void main(String[] args) {
    List<String> allMatches = new ArrayList<String>();
    Matcher m = Pattern.compile("\\d+\\D+\\d+").matcher("2abc3abc4abc5");
    while (m.find()) {
        allMatches.add(m.group());
    }

    String[] res = allMatches.toArray(new String[0]);
    System.out.println(Arrays.toString(res));
}
Run Code Online (Sandbox Code Playgroud)

结果是:

[2abc3, 4abc5]
Run Code Online (Sandbox Code Playgroud)

我希望它是

[2abc3, 3abc4, 4abc5]
Run Code Online (Sandbox Code Playgroud)

如何实现?

Ham*_*mZa 16

不确定这是否可以在Java中使用,但在PCRE中您可以执行以下操作:
(?=(\d+\D+\d+)).

解释
该技术是在先行中使用匹配组,然后"吃掉"一个字符向前移动.

  • (?= :积极前瞻的开始
    • ( :开始匹配组1
      • \d+ :匹配数字一次或多次
      • \D+ :匹配非数字字符一次或多次
      • \d+ :匹配数字一次或多次
    • ) :第1组结束
  • ) :前瞻的结束
  • . :匹配任何东西,这是"前进".

在线演示


感谢Casimir et Hippolyte,它似乎真的适用于Java.您只需要添加反斜杠并显示第一个捕获组:(?=(\\d+\\D+\\d+))..在www.regexplanet.com上测试:

在此输入图像描述

  • @ johnchen902:你必须用`(?=((?<!\\ d)\\ d + \\ D + \\ d +))`替换模式``如果你不想在重叠的结果中重叠结果.:) (5认同)
  • 不是真的有效.使用`12abc13abc14abc15`作为输入,结果是`[12abc13,2abc13,13abc14,3abc14,14abc15,4abc15]`而不是`[12abc13,13abc14,14abc15]`.请参阅我和OP在该问题下的评论. (2认同)

joh*_*902 16

使匹配器尝试从后者开始下一次扫描\d+.

Matcher m = Pattern.compile("\\d+\\D+(\\d+)").matcher("2abc3abc4abc5");
if (m.find()) {
    do {
        allMatches.add(m.group());
    } while (m.find(m.start(1)));
}
Run Code Online (Sandbox Code Playgroud)


小智 5

HamZa的上述解决方案在Java中完美运行。如果你想在文本中找到特定的模式,你所要做的就是:

String regex = "\d+\D+\d+";

String updatedRegex = "(?=(" + regex + ")).";
Run Code Online (Sandbox Code Playgroud)

哪里regex是您正在寻找的图案并且要重叠,您需要(?=(" at the start and ")).在最后用它包围它。