我想在字符串的可选部分中捕获一个组。
例如:
在字符串" firstName:Bill-lastName:Gates" 中,我想捕获2组:
我使用这个正则表达式:
firstName:(.*)-lastName:(.*)
但是当lastName-part是可选的时,我仍然希望捕获第一个 group(firstName)。
我使用了这个正则表达式,使lastName-part可选(在非捕获组中):
firstName:(.*)(?:-lastName:(.*))?
使用此更新的正则表达式,生成的组为:
当lastName部分不存在时,例如" firstName:Bill" 捕获的组是:
正确,
当firstName和lastName部分存在时:" firstName:Bill-lastName:Gates" ,组不正确:
我认为这与第一个捕获组的贪婪有关,但是当lastName-part是可选的时,如何调整此正则表达式以使正则表达式工作?
答案 0 :(得分:4)
你是对的,这是关于贪婪的。找到第一个匹配组的分隔符。因此,如果您的名字“never”包含短划线,则只匹配除第一个匹配组的短划线以外的所有内容。
firstName:([^-]*)(?:-lastName:(.*))?
firstName:([^-]*)(?:-lastName:(.*))?
如果找不到这样的分隔符,则需要采用不同的方法。即使您尝试将第一个模式设置为“懒惰”,Regex引擎也始终优先选择更大的匹配,而不是匹配其他可选匹配。
这是因为 lazy matchgroups将匹配满足表达式的第一个字符串(!重要的措辞!)
可能有一个look arrounds选项,但您也可以使用or -statement而不提供可选匹配:
firstName:(.*)-lastName:(.*)|firstName:(.*)
这样,正则表达式引擎会匹配任何一个或,但更喜欢具有2个匹配的模式,因为它首先列出。只有在不适用的情况下,它才会尝试单一匹配。
答案 1 :(得分:2)
即使你已经接受了@ dognose的回答,我向你保证,其中有一些带有破折号的名字(你不想惹恼Jean-Claude van Damme)。我会建议你这样做:
firstName:((?:(?!-lastName:).)*)(?:-lastName:(.*))?
您可以从可视化中看到(?:(?!-lastName:).)
说“如果当前位置后面没有' -lastName:',则会捕获另一个字符”