最近我在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都会被覆盖。
但我仍然希望你能给我一些好消息......
答案 0 :(得分:5)
不,不幸的是,正如您的引文已经提到的那样,java.util.regex正则表达式实现不支持在单个匹配后检索重复捕获组的任何先前值。正如您的代码所示,获取这些内容的唯一方法是通过find()对正则表达式的重复部分进行多次匹配。
我也一直在研究Java中正则表达式的其他实现,例如:
但我找不到任何支持它(只有Microsoft .NET引擎)。如果我理解正确,基于状态机的正则表达式的实现不能轻易实现此功能。但是,java.util.regex不使用状态机。
如果有人知道支持此行为的Java正则表达式库,请分享它,因为它将是一个强大的功能。
P.S。我花了很长时间才明白你的问题。标题很好,但是身体让我困惑于我是否理解正确。