[英]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.