如何捕获其他2个组之间的可选组

时间:2019-09-11 00:33:21

标签: regex

假设我有以下字符串: 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

任何帮助将不胜感激

1 个答案:

答案 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')

最终将导致匹配在相同的组索引处始终具有相同的匹配,但是我真的不喜欢该解决方案。如果您陈述了为什么要尝试与此匹配,那么我很确定有比这更好的方法来实现目标。