我得到一些像这样的字符串:\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次而第二个(?:\{[^\{\}\[\]]*\})*?
匹配1次,则会捕获sadf
;如果第一个(?:\{[^\{\}\[\]]*\})*?
匹配1次,第二个匹配0次,它将捕获ad
。但是,它只会使用此正则表达式返回['sadf']
。
没有所有这些额外的模式((?:\\mypath\{)
和(?:\})
),它实际上有效:
>>> p2=re.compile(r'(?:\{[^\{\}\[\]]*\})*?\{([^\{\}\[\]]*)\}(?:\{[^\{\}\[\]]*\})*?')
>>> p2.findall(strpath)
['sadf', 'ad']
>>> p2.findall('{adadd}{dfada}{adafadf}')
['adadd', 'dfada', 'adafadf']
任何人都可以向我解释这种行为吗?有没有更聪明的方法来实现我想要的结果?
答案 0 :(得分:1)
你是对的。无法在组内返回重复的子组。要执行所需操作,可以使用正则表达式捕获组,然后使用第二个正则表达式捕获重复的子组。
在这种情况下,类似于:\\mypath{(?:\{.*?\})}
。这将返回{path1}{path2}{path3}
然后要在该字符串中找到{pathn}
的重复模式,您只需使用\{(.*?)\}
即可。这将匹配任何与括号。 .*?
是.*
的非贪婪版本,这意味着它将返回最短的匹配,而不是最长的匹配。
答案 1 :(得分:1)
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 {}