簡體   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