1

我得到一些这样\input{{whatever}{1}}\mypath{{path1}{path2}{path3}...{pathn}}\shape{{0.2}{0.3}} 的字符串:我想捕获所有路径:path1,path2,... pathn。re我在python中尝试了该模块。但是,它不支持多次捕获。例如: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 次,第二个(?:\{[^\{\}\[\]]*\})*?匹配 1 次,它将捕获sadf;如果第一个(?:\{[^\{\}\[\]]*\})*?匹配 1 次,第二个匹配 0 次,它将捕获ad. 但是,它只会返回['sadf']这个正则表达式。

没有所有这些额外的模式((?:\\mypath\{)(?:\})),它实际上可以工作:

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

谁能向我解释这种行为?有没有更聪明的方法来达到我想要的结果?

4

2 回答 2

2
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 {}
于 2012-09-28T13:38:55.117 回答
1

你说的对。不能在组内返回重复的子组。要执行您想要的操作,您可以使用正则表达式来捕获组,然后使用第二个正则表达式来捕获重复的子组。

在这种情况下,这将是这样的:\\mypath{(?:\{.*?\})}. 这将返回{path1}{path2}{path3}

然后要找到该{pathn}字符串内部的重复模式,您可以简单地使用\{(.*?)\}. 这将匹配任何带有大括号的东西。是的.*?非贪婪版本.*,这意味着它将返回可能的最短匹配,而不是可能的最长匹配。

于 2012-09-28T13:38:18.487 回答