【问题标题】:Java regex - overlapping matchesJava 正则表达式 - 重叠匹配
【发布时间】:2013-07-31 13:15:18
【问题描述】:

在以下代码中:

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

结果是:

[2abc3, 4abc5]

我希望是

[2abc3, 3abc4, 4abc5]

如何实现?

【问题讨论】:

  • 你需要从每个索引开始搜索;使用 find(int startingIndex) 方法并从每个字符位置开始搜索。当然,那么您可能会找到太多匹配项......假设您想从每个数字开始,您可能会尝试在 Matcher.find(String.indexOf(digits, index)) 上为所有匹配索引组合迭代。
  • 我想如果是个位数,你可以从比赛开始位置倒退,从那里找到下一场比赛。
  • 对于输入"12abc13abc14abc15",你要[12abc13, 2abc13, 13abc14, 3abc14, 14abc15, 4abc15]还是[12abc13, 13abc14, 14abc15]
  • @johnchen902:后者。解决方案可以解决这个问题。

标签: java regex


【解决方案1】:

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

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

【讨论】:

  • 致前两个投票者:普通版本包含一个错误,如果没有匹配,IllegalStateException 将被抛出。
【解决方案2】:

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

说明
该技术是在前瞻中使用匹配组,然后“吃掉”一个字符以向前移动。

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

Online demo


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

【讨论】:

  • @anubhava 它为 PCRE 提供了正确的结果。反正我就是这么说的。
  • 是的,我只是说在 Java 中它没有给出预期的结果。
  • @anubhava:我已经对其进行了测试,并且效果很好,假设您添加了反斜杠并显示了第一个捕获组。 downvoter:downvote 在这里毫无意义。
  • 没有真正的工作。使用12abc13abc14abc15 作为输入,结果是[12abc13, 2abc13, 13abc14, 3abc14, 14abc15, 4abc15] 而不是[12abc13, 13abc14, 14abc15]。在问题下查看我和 OP 的 cmets。
  • @johnchen902:是的,如果您不想在重叠结果中出现重叠结果,则必须将模式替换为 (?=((?&lt;!\\d)\\d+\\D+\\d+))。 :)
【解决方案3】:

HamZa 的上述解决方案在 Java 中完美运行。如果您想在文本中找到特定模式,您只需:

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

String updatedRegex = "(?=(" + regex + ")).";

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-10
    • 2011-05-16
    • 2010-09-24
    • 2021-02-16
    • 2013-04-05
    相关资源
    最近更新 更多