我正在尝试匹配以下格式的字符串:
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'中描述的内容有关。我试图用我的正则表达式来摆弄一下,但仍然没有令人满意的结果。有什么建议?
答案 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”和你的结果一样..