假设我有以下字符串:
anything/AAA/B/B/B/anything
我想在4个不同的组中匹配anything/
,AAA/
,B/B/B/
,anything
。
AAA/
和B/B/B/
是可选的,anything
可以是任何字符串
,因此以下字符串anything/AAA/B/B/B/anything
的结果为
群组1:anything/
组2:AAA/
组3:B/B/B/
组4:anything
,以下字符串anything/anything
的结果将为
群组1:anything/
组2:空
组3:空
组4:anything
我尝试了以下正则表达式:
^(.*?/)(AAA/)?(B/B/B/)?(.*?)$
问题在于,当第一个anything
包含/
时,未捕获可选组
因此以下字符串any/thing/AAA/B/B/B/anything
的结果将为
群组1:any/
组2:空
组3:空
组4:thing/AAA/B/B/B/anything
我希望它像这样:
群组1:any/thing
组2:AAA/
组3:B/B/B/
组4:anything
任何帮助将不胜感激
答案 0 :(得分:0)
您的问题是,“任何东西”都可以成为任何东西。
因此,当您使它变得贪婪时,它可以匹配'AAA/'
或'B/B/B/'
之前的所有内容。但是,当您使它不贪婪时(如您的示例所示),它将尝试为该第一个匹配组尽可能少地匹配,并返回它的结果(如果它可以使其工作),并且可以通过仅匹配其余部分来返回到最后的“任何内容”,即(.*?)
。即使这不是贪婪的,它也仅适用于字符串的结尾,并且一旦到达主题字符串的结尾而没有违反规则,就完成了。
您可能会认为将'AAA/'
或'B/B/B/'
匹配成单独的组会使最终的组变得“更少贪婪”,但是regex引擎不会遍历所有可能的匹配项,并且会给您“最小贪婪” ',它将返回它可以找到的第一个匹配项。
因此,尽管我希望证明自己被证明是错误的,但我认为您无法一劳永逸地在正面和背面都拥有“任何东西”。
根据您的语言(以Python给出的示例),您可以连续进行几次匹配:
import re
def get_matches(s):
match = re.search(r'^(.*?/)(AAA/)(B/B/B/)(.*?)$', s)
if not match:
match = re.search(r'^(.*?/)(AAA/)()(.*?)$', s)
if not match:
match = re.search(r'^(.*?/)()(B/B/B/)(.*?)$', s)
if not match:
if not match:
match = re.search(r'^(.*?/)()()(.*?)$', s)
return match
print(get_matches('anything/AAA/B/B/B/anything').groups())
print(get_matches('anything/AAA/anything').groups())
print(get_matches('anything/B/B/B/anything').groups())
print(get_matches('anything/anything').groups())
结果:
('anything/', 'AAA/', 'B/B/B/', 'anything')
('anything/', 'AAA/', '', 'anything')
('anything/', '', 'B/B/B/', 'anything')
('anything/', '', '', 'anything')
最终将导致匹配在相同的组索引处始终具有相同的匹配,但是我真的不喜欢该解决方案。如果您陈述了为什么要尝试与此匹配,那么我很确定有比这更好的方法来实现目标。