Python 如何使用正则表达式捕获多个重复模式?
我得到如下字符串:Python 如何使用正则表达式捕获多个重复模式?,python,regex,Python,Regex,我得到如下字符串:\input{{whatever}{1}}\mypath{{path1}{path2}{path3}…{pathn}\shape{{0.2}{0.3} 我想捕获所有路径:路径1,路径2。。。帕恩。我尝试了python中的re模块。但是,它不支持多个捕获。 例如:r“\\mypath\{(\{[^\{\\\[\]*\})*\}”将只返回最后匹配的组。将模式应用于search(r“\mypath{{{path1}{path2}})”将只返回groups()作为(“{path2}”,
\input{{whatever}{1}}\mypath{{path1}{path2}{path3}…{pathn}\shape{{0.2}{0.3}
我想捕获所有路径:路径1,路径2。。。帕恩。我尝试了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']
或:
此时,我想,为什么不在原始字符串上使用findall呢?我可以使用:
gpathRegexPat=r“(?:\\mypath\{)(?:\{[^\\\\[\]*})*.{([^\\\\\[\]]*])(:{[^\\\\\\\\[\]]*})*.(?:\})
:如果第一个(?:{[^\\\\\\\\\\[\]*})*.*}匹配0个时间,第二个(?:{\\\\\\\\\\\\\[\\\\\\\\\\\\[]*]代码匹配[\\\\\\\\\\\\\\\\\\\\\\[]*}时间,它将捕获;如果第一个(?:\{[^\{\\\[\]]*\})*?
匹配1次,第二个匹配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 {}
re.findall({(path\d+}),text)#将只返回类似于{}内路径的内容
要遵守王的路径规范,正则表达式应该是“代码>R”{[{[{}[\] ] * ] }“/Cux> @ Joran,谢谢回答,但是考虑一个字符串隐藏在其他字符中:<代码>输入{{ }}{ 1 } \ MyPATH {{PATH1}{PATH2}{PAT3.}}{PATN}}{{{ 0.1 }{ 0.2 }} < /代码>。它还将捕获input{}
和\shape{}
中的参数。我想它仍然需要使用两步捕获。@Joran Beasley,谢谢!所以这也是两步走。你能再解释一下为什么正则表达式r“(?:\\mypath\{)(?:\{[^\{\\\\[\]]*})*?\{([^\{\\\\[\]]*])\}(?:{[^\\\\\\[\]*})*?(?)?:\})"
也不能用findall()
返回所有路径?不,使用regex你想让它们保持简短…长regex需要很长时间才能解码…@Wang:提取序列(步骤1):L=re.findall(r“\\mypath{({.*}),输入文本)
(假设\mypath
出现多次).Step 2:对于列表中的每个项L
调用re.findall(“{([^{}]+)}”,item)
注意:模块支持重复捕获。尽管在此过程中不需要它们case@Sebastian.谢谢!我想这不是一个内置模块。@Hans那么。谢谢!你能再解释一下为什么正则表达式r“(?:\\mypath\{)(?:\{[^\\}\[\]]*})*?\{([^\{\\\[\]]*)\}(?:\{[^\\\\[\]]*})*?(?:\})
无法返回具有findall()的所有路径
不是吗?这是因为findall
将只返回与正则表达式匹配的模式。由于以\mypath
开头,findall
将只返回以该字符串开头的匹配项,其中只有一个字符串。
re.findall("{(path\d+)}",text) #will only return things like path<num> inside {}