多次捕获组

时间:2014-11-06 07:21:54

标签: java regex regex-group

最近我在Java中使用正则表达式,我发现自己陷入了一个(理论上)很容易解决的问题,但是如果有更简单的方法可以解决这个问题(是的,我是懒惰的) ),问题是多次捕获一个组,这是:

public static void main(String[] args) {
    Pattern p = Pattern.compile("A (IvI(.*?)IvI)*? A");
    Matcher m = p.matcher("A IvI asd IvI IvI qwe IvI A"); //ANY NUMBER of IvI x IvI
    //Matcher m = p.matcher("A  A");
    int loi = 0; //last Occurrence Index
    String storage;
    while (loi >= 0 && m.find(loi)) {
        System.out.println(m.group(1));
        if ((storage = m.group(2)) != null) {
            System.out.println(storage);
        }
        //System.out.println(m.group(1));
        loi = m.end(1);
    }
    m.find();
    System.out.println("2 opt");
    Pattern p2 = Pattern.compile("IvI(.*?)IvI");
    Matcher m2 = p2.matcher(m.group(1)); //m.group(1) = "IvI asd IvI IvI qwe IvI"
    loi = 0;
    while (loi >= 0 && m2.find(loi)) {
        if ((storage = m2.group(1)) != null) {
            System.out.println(storage);
        }
        loi = m2.end(0);
    }
}

使用 Pattern p 是否有办法获取IvI's内的内容?(在测试字符串中将是" asd"和" qwe")考虑到可能有任意数量的IvI's部分,类似于我在第一次尝试时所做的事情,即找到第一次出现的组,然后移动索引并搜索下一组,依此类推......

使用我写的代码,虽然它返回asd IvI IvI qwe作为组2,而不只是asd然后qwe,部分我认为它可能是因为(。 *?)部分,不应该是贪婪的,但它仍然会消耗qwe消耗IvI's中的两个,我提到这个,因为否则我可以使用那些的结束索引使用matcher.find(anInt)方法,但它也不起作用;我认为正则表达式没有任何问题,因为下一个代码无法使用IvI

public static void main(String[] args) {
    Pattern p = Pattern.compile("(.*?)IvI");
    Matcher m = p.matcher("bla bla blaIvI");
    m.find();
    System.out.println(m.group(1));
}

打印:bla bla bla

我知道有一个解决方案(但我很懒,还记得)

(也在第一个代码上,下面是" 2 opt"消息) 解决方案是将其划分为子组并使用另一个正则表达式,您一次只处理一个子组...

顺便说一句:我完成了我的作业 在this页面中提及

  

由于具有量词的捕获组会保留其数字,因此当您检查组时,引擎会返回什么值?所有引擎都返回捕获的最后一个值。例如,如果您将字符串A_B_C_D_与([A-Z] )+匹配,则在检查匹配时,组1将为D 。除.NET引擎外,所有中间值都将丢失。从本质上讲,每次匹配模式时,组1都会被覆盖。

但我仍然希望你能给我一些好消息......

1 个答案:

答案 0 :(得分:5)

不,不幸的是,正如您的引文已经提到的那样,java.util.regex正则表达式实现不支持在单个匹配后检索重复捕获组的任何先前值。正如您的代码所示,获取这些内容的唯一方法是通过find()对正则表达式的重复部分进行多次匹配。

我也一直在研究Java中正则表达式的其他实现,例如:

但我找不到任何支持它(只有Microsoft .NET引擎)。如果我理解正确,基于状态机的正则表达式的实现不能轻易实现此功能。但是,java.util.regex不使用状态机。

如果有人知道支持此行为的Java正则表达式库,请分享它,因为它将是一个强大的功能。

P.S。我花了很长时间才明白你的问题。标题很好,但是身体让我困惑于我是否理解正确。