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

时间:2011-02-16 15:41:35

标签: java regex

是否可以创建具有可变数量的组的正则表达式?

以此为例运行......

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"

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


正如@Tim Pietzcker在评论中指出的那样,perl6.NET具有此功能。

7 个答案:

答案 0 :(得分:20)

根据documentation,Java正则表达式不能这样做:

  

与a关联的捕获输入   小组总是后续的   该群组最近匹配。如果一个   小组第二次评估   因为量化然后它   以前捕获的值,如果有的话,   如果是第二个,将被保留   评估失败。匹配字符串   “aba”反对表达式(a(b)?)+,   例如,将第二组设置为   “B”。所有捕获的输入都被丢弃   在每场比赛开始时。

(强调补充)

答案 1 :(得分:3)

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无法做到这一点。您可以在Bars的匹配上递归和使用正则表达式,或者使用像ANTLR这样的解析器生成器,并将副作用附加到Bar

答案 2 :(得分:3)

您可以使用split将所需的字段放入数组中并循环显示。

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

答案 3 :(得分:2)

我没有使用java正则表达式,但对于许多语言,答案是:否。

捕获组似乎是在解析正则表达式时创建的,并在匹配字符串时填充。表达式(a)|(b)(c)有三个捕获组,只有当其中一个或两个可以填充时。 (a)*只有一个组,解析器在匹配后保留组中的最后一个匹配。

答案 4 :(得分:0)

我认为回溯会抑制这种行为,并说/([\S\s])/在其分组累积状态中对圣经这样的行为的影响。即使可以做到,输出也是不可知的,因为这些组将失去位置意义。最好在全局意义上对类似的regex做一个单独的正则表达式并将其存放到数组中。

答案 5 :(得分:0)

我刚刚遇到了类似的问题,并设法做了“可变数量的组”但是组合了一个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();
    }

您无法使用*+指定任意长度的重复,因为前瞻和后视必须具有可预测的长度。

答案 6 :(得分:0)

如果您遇到的匹配组的最大数量合理:

"ab([cd])?([cd])?([cd])?([cd])?([cd])?([cd])?([cd])?([cd])?ef"

此示例适用于 0 - 8 个匹配项。我承认这很丑陋,而且不是人类可读的。