如何在 java 正则表达式中使用贪婪量词 X* 时保留 X 的所有出现次数



我有一个正则表达式,用于查找字符串内<>之间的逗号分隔单词列表的匹配项,如示例中的"Hello <a1> sqjsjqk <b1,b2> dsjkfjkdsf <c1,c2,c3> ffsd"

我想使用捕获组来保留大括号之间的每个单词:

这是我的表达式:< (w+) (?: ,(w+) )* >(添加空格是为了可读性,但不是模式的一部分)

括号用于创建捕获组,(?: )用于创建非捕获组,因为我不想保留昏迷。

这是我的测试代码:

@Test
public void test() {
    String patternString = "<(\w+)(?:,(\w+))*>";
    Pattern pattern = Pattern.compile(patternString);
    Matcher matcher = pattern.matcher("Hello <a1> sqjsjqk <b1,b2> dsjkfjkdsf <c1,c2,c3> ffsd");
    while(matcher.find()) {
        System.out.println("== Match ==");
        MatchResult matchResult = matcher.toMatchResult();
        for(int i = 0; i < matchResult.groupCount(); i++) {
            System.out.println("  " + matchResult.group(i + 1));
        }
    }
}

这是生成的输出:

== Match ==
  a1
  null
== Match ==
  b1
  b2
== Match ==
  c1
  c3

这就是我想要的:

== Match ==
  a1
== Match ==
  b1
  b2
== Match ==
  c1
  c2
  c3

由此我了解到,我的表达式中的组数与捕获组的数量正好一样多,但这不是我想要的,因为我需要所有被识别为w+的子字符串

有没有机会用一个正则表达式得到我想要的东西,或者我应该用split(",")trim()等来完成这项工作......

据我所知,.NET 拥有唯一的正则表达式引擎,可以为单个捕获组返回多个捕获。所以你所要求的在Java中是不可能的(至少不是你要求的方式)。

但是,在您

的情况下,可以在一定程度上解决此问题。如果你能确定永远不会有不匹配的收盘>,你可以做出你想要捕捉完整匹配的东西,并通过前瞻要求正确的位置:

"\w+(?=(?:,\w+)*>)"

这永远无法匹配<...>之外的"单词",因为它们无法通过开场<来匹配结束>。当然,这使得很难区分来自不同<...>集的元素。

或者(我想这更好,因为它更安全,更具可读性),选择两步算法。第一场比赛

"<([\w,]*)>"

然后在, split每个结果的第一次捕获。

最新更新