无法使用REGEX捕获字符串中的组

时间:2012-04-25 06:12:32

标签: regex

我正在尝试匹配以下格式的字符串:

S->A  
S->AbCd  
S->A|b|C|d  
S->Ab|B|cde|dB 

也就是说,在最左侧,只有一个大写拉丁字母符号后跟' - >'文字。在该文字后面恰好是一个大写/非大写拉丁字母符号或这些符号的串联,这些符号也可以跟随由“|”分隔的这些符号组。符号。
此外,我不仅要检查整个字符串是否符合此格式,还要能够捕获最左边的大写符号和' - >'后的所有符号组。文字。到目前为止,我已经提出了这个正则表达式:

([A-Z]{1})->([a-zA-Z]+)(?:(?:\|)([a-zA-Z]+))*

如果我对它进行测试,例如,这个字符串:

S->Ab|B|c|d

我得到以下结果(使用RegexBuddy进行测试):

Match 1:    S->Ab|B|c|d
Group 1:    S
Group 2:    Ab
Group 3:    d

好消息是我的正则表达式匹配整个字符串(这是正确的)。然而问题显而易见:我的正则表达式只捕获' - >'之后的第一个和最后一个符号组。文字。为什么?根据我对正则表达式的理解,这部分表达式

(?:(?:\|)([a-zA-Z]+))*

应匹配所有分隔符号组。我认为这与文章'Repeating a Capturing Group vs. Capturing a Repeated Group'中描述的内容有关。我试图用我的正则表达式来摆弄一下,但仍然没有令人满意的结果。有什么建议?

4 个答案:

答案 0 :(得分:2)

正则表达式中只有三对捕获括号,因此您只能获得三组(并且它与'捕获重复组而不是重复捕获组'相关)。组的数量始终是固定的。

为了清晰起见,使用类似Perl的间距m//x进行拆分:

([a-zA-Z]{1})  ->  ([a-zA-Z]+)  (?: (?:\|) ([a-zA-Z]+) )*
^-----------^      ^---------^             ^---------^

显示了三个捕获部分。其他括号是非捕获的。显然,您可以捕获整个尾随组:

    ([a-zA-Z]{1})  ->  ([a-zA-Z]+)  ( (?:\|) (?:[a-zA-Z]+) )*

但是你需要对尾随组进行后处理,可能需要split操作来获取子字段。

答案 1 :(得分:1)

语法(?:...)表示非捕获组。

如果您想要捕获组,则应使用(...)代替。

试试这个:

([a-zA-Z]{1})->([a-zA-Z]+)(\|[a-zA-Z]+)*

如果您希望单独使用每个元素,则可以在分隔符上进行拆分。

答案 2 :(得分:1)

是的,您的问题是,您正在重复捕获组。

(?:(?:\|)([a-zA-Z]+))*
         ^^^^^^^^^^^
          third group

你是对的,整个部分都匹配你所有的重复组,每个匹配都存储在$3中,所以在完成所有匹配后的结果,你只能看到这个组的最后一个匹配,在您的示例中为d

您可以像这样捕获重复的组

([a-zA-Z]{1})->([a-zA-Z]+)((?:(?:\|)[a-zA-Z]+)*)

然后你的结果看起来像这样

Match 1:    S->Ab|B|c|d
Group 1:    S
Group 2:    Ab
Group 3:    |B|c|d

答案 3 :(得分:1)

捕获组3匹配所有符号([a-zA-Z]+) - 它将首先匹配“B”,然后当下一个|之后正则表达式进展时它被“c”替换,最后它被替换为“d”和你的结果一样..