具有可变数量的组的正则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(); }
你失去了用*
或+
来指定任意重复长度的能力,因为先行和后退必须是可预测的长度。