繁体   English   中英

如何使用正则表达式捕获多个重复模式?

[英]How to capture multiple repeating patterns with regular expression?

我得到一些像这样的字符串: \\input{{whatever}{1}}\\mypath{{path1}{path2}{path3}...{pathn}}\\shape{{0.2}{0.3}}我想捕获所有路径:path1,path2,... pathn。 我在python中尝试了re模块。 但是,它不支持多次捕获。 例如: r"\\\\mypath\\{(\\{[^\\{\\}\\[\\]]*\\})*\\}"将仅返回最后一个匹配的组。 将模式应用于search(r"\\mypath{{path1}{path2}})"只会将groups()返回为("{path2}",)

然后我找到了另一种方法:

    gpathRegexPat=r"(?:\\mypath\{)((\{[^\{\}\[\]]*\})*)(?:\})"
    gpathRegexCp=re.compile(gpathRegexPat)
    strpath=gpathRegexCp.search(r'\mypath{{sadf}{ad}}').groups()[0]
    >>> strpath
    '{sadf}{ad}'
    p=re.compile('\{([^\{\}\[\]]*)\}')
    >>> p.findall(strpath)
    ['sadf', 'ad']

要么:

    >>> gpathRegexPat=r"\\mypath\{(\{[^{}[\]]*\})*\}"
    >>> gpathRegexCp=re.compile(gpathRegexPat, flags=re.I|re.U)
    >>> strpath=gpathRegexCp.search(r'\input{{whatever]{1}}\mypath{{sadf}{ad}}\shape{{0.2}{0.1}}').group()
    >>> strpath
    '\\mypath{{sadf}{ad}}'
    >>> p.findall(strpath)
    ['sadf', 'ad']

在这一点上,我想,为什么不在原始字符串上使用findall? 我可以使用: gpathRegexPat=r"(?:\\\\mypath\\{)(?:\\{[^\\{\\}\\[\\]]*\\})*?\\{([^\\{\\}\\[\\]]*)\\}(?:\\{[^\\{\\}\\[\\]]*\\})*?(?:\\})" :如果是第一个(?:\\{[^\\{\\}\\[\\]]*\\})*? 匹配0时间和第2 (?:\\{[^\\{\\}\\[\\]]*\\})*? 匹配1次,它将捕获sadf ; 如果是第一个(?:\\{[^\\{\\}\\[\\]]*\\})*? 匹配1次,第2次匹配0次,它将捕获ad 但是,它只会使用此正则表达式返回['sadf']

除了所有这些额外的模式( (?:\\\\mypath\\{)(?:\\}) ),它实际上有效:

    >>> p2=re.compile(r'(?:\{[^\{\}\[\]]*\})*?\{([^\{\}\[\]]*)\}(?:\{[^\{\}\[\]]*\})*?')
    >>> p2.findall(strpath)
    ['sadf', 'ad']
    >>> p2.findall('{adadd}{dfada}{adafadf}')
    ['adadd', 'dfada', 'adafadf']

任何人都可以向我解释这种行为吗? 有没有更聪明的方法来实现我想要的结果?

你是对的。 无法在组内返回重复的子组。 要执行所需操作,可以使用正则表达式捕获组,然后使用第二个正则表达式捕获重复的子组。

在这种情况下,类似于: \\\\mypath{(?:\\{.*?\\})} 这将返回{path1}{path2}{path3}

然后,要在该字符串中找到{pathn}的重复模式,您只需使用\\{(.*?)\\} 这将匹配任何与括号。 .*? .*的非贪婪版本,意味着它将返回最短的匹配而不是最长的匹配。

re.findall("{([^{}]+)}",text)

应该管用

回报

['path1', 'path2', 'path3', 'pathn']

最后

my_path = r"\input{{whatever}{1}}\mypath{{path1}{path2}{path3}...{pathn}}\shape{{0.2}{0.3}}"
#get the \mypath part
my_path2 = [p for p in my_path.split("\\") if p.startswith("mypath")][0]
print re.findall("{([^{}]+)}",my_path2)

甚至更好

re.findall("{(path\d+)}",text) #will only return things like path<num> inside {}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM