RegEx:分组仅返回最后一个匹配

时间:2012-06-05 00:02:06

标签: regex pattern-matching

我有一组这种形式的字符串:

NOOO (2), { AAA (1), BBB (2), CCC-CC (3), DDD (4) }

(括号内的元素可以多于四个)

我需要匹配括号内的内容并仅提取(使用组)'AAA','BBB',...子串。所以这个例子的结果将是

group1 : AAA
group2 : BBB
group3 : CCC-CC
group4 : DDD

我尝试了这个表达式:

\{ (?:(\S+) \(\d+\),?\s?)+ \}

但它只返回最后一个匹配的组(因此,在这种情况下,只返回'DDD')。我错过了什么?感谢

1 个答案:

答案 0 :(得分:3)

如果您使用的是.NET正则表达式,那么您的表达式将起作用,因为捕获组将捕获其所有值。否则,您必须使用更棘手的正则表达式或分两步匹配,首先匹配{ ... }组,然后匹配其中的元素。

棘手的正则表达式看起来像:

(?:{|\G(?!^),)   # match a { or where the previous match ended followed by a ,
\s+              # space between elements
(\S+)\s+\(\d+\)  # an element
(?=[^{]*})       # make sure it's eventually followed by a }

如果使用/x标志,也可以使用该表达式(也可以通过在表达式的开头添加(?x)来设置)。

没有评论的正则表达式:

(?:{|\G(?!^),)\s+(\S+)\s+\(\d+\)(?=[^{]*})

此表达式使用您的正则表达式必须支持的\G。 大多数现代正则表达式都有它,包括:Perl,PCRE(PHP / etc),.NET。

请注意,这样的表达并不完美。它会捕获以下字符串中的AAABBB,例如:

{ AAA (1), BBB (23), CCC, something invalid here #¤% ))),,,,!! }

如果需要,可以修复(计数器除外)。