具有可变数量的组的正则expression式?

是否有可能创build一个具有可变数量的组的正则expression式?

运行这个例如…

Pattern p = Pattern.compile("ab([cd])*ef"); Matcher m = p.matcher("abcddcef"); m.matches(); 

…我想有类似的东西

  • m.group(1) = "c"
  • m.group(2) = "d"
  • m.group(3) = "d"
  • m.group(4) = "c"

(背景:我正在parsing一些数据行,其中一个“字段”是重复的,我想避免这些字段的matcher.find循环。


正如@Tim Pietzcker在评论中指出的, perl6和.NET有这个特性。

根据文档 ,Java正则expression式不能这样做:

与组关联的捕获的input始终是组最近匹配的子序列。 如果一个小组由于量化而被第二次评估,那么如果第二次评估失败,则其先前捕获的值(如果有的话)将被保留。 例如,将string“aba”与expression式(a(b)?)+匹配,会将第二组设置为“b”。 所有捕获的input在每场比赛开始时被丢弃。

(强调加)

 Pattern p = Pattern.compile("ab(?:(c)|(d))*ef"); Matcher m = p.matcher("abcdef"); m.matches(); 

应该做你想做的。

编辑:

@aioobe,我现在明白了。 你希望能够做一些类似语法的事情

 A ::== <Foo> <Bars> <Baz> Foo ::== "foo" Baz ::== "baz" Bars ::== <Bar> <Bars> | ε Bar ::== "A" | "B" 

并拔出Bar所有单独的匹配。

不,使用java.util.regex没有办法做到这一点。 你可以recursion和使用一个正则expression式在Bars的匹配上,或者使用像ANTLR这样的parsing器生成器,并且为Bar添加一个副作用。

你可以使用split来获得你需要的字段到数组中并循环。

http://download.oracle.com/javase/1,5.0/docs/api/java/lang/String.html#split(java.lang.String

我没有使用Java的正则expression式,但对于许多语言的答案是:没有。

当正则expression式被parsing时,捕获组似乎被创build,并且当匹配string时被填充。 expression式(a)|(b)(c)有三个捕获组,只有当其中一个或两个可以填充时。 (a)*只有一个组,parsing器在匹配之后离开组中的最后一个匹配。

我认为回溯抑制了这种行为,并且说明了/([\S\s])/在其分类累积状态中对圣经的影响。 即使可以完成,输出也是不可知的,因为这些组将失去位置的意义。 更好的做法是在全局意义上做类似的正则expression式,并将其存入数组中。

我刚刚有类似的问题,并设法做“可变数量的组”,但一个while循环的组合和重置匹配器。

  int i=0; String m1=null, m2=null; while(matcher.find(i) && (m1=matcher.group(1))!=null && (m2=matcher.group(2))!=null) { // do work on two found groups i=matcher.end(); } 

但这是为了我的问题(有两个重复

  Pattern pattern = Pattern.compile("(?<=^ab[cd]{0,100})[cd](?=[cd]{0,100}ef$)"); Matcher matcher = pattern.matcher("abcddcef") int i=0; String res=null; while(matcher.find(i) && (res=matcher.group())!=null) { System.out.println(res); i=matcher.end(); } 

你失去了用*+来指定任意重复长度的能力,因为先行和后退必须是可预测的长度。