簡體   English   中英

正則表達式中的條件匹配

[英]Conditional matching in regular expression

我正在嘗試從下面給出的字符串中提取一些信息

>>> st = '''
... <!-- info mp3 here -->
...                             192 kbps<br />2:41<br />3.71 mb  </div>
... <!-- info mp3 here -->
...                             3.49 mb  </div>
... <!-- info mp3 here -->
...                             128 kbps<br />3:31<br />3.3 mb   </div>
... '''
>>>

現在當我使用下面的正則表達式我的輸出是

>>> p = re.findall(r'<!-- info mp3 here -->\s+(.*?)<br />(.*?)<br />(.*?)\s+</div>',st)
>>> p
[('192 kbps', '2:41', '3.71 mb'), ('128 kbps', '3:31', '3.3 mb')]

但我要求的輸出是

[('192 kbps', '2:41', '3.71 mb'),(None,None,'3.49mb'), ('128 kbps', '3:31', '3.3 mb')]

所以,我的問題是如何更改我的上述regex以匹配所有條件。我相信我當前的正則表達式嚴格依賴於<br />標簽,所以我如何使其成為條件。

我知道我不應該使用正則表達式來解析HTML,但目前這對我來說是最合適的方式。

以下內容可行,但我想知道是否沒有更優雅的解決方案。 你當然可以將列表推導組合成一行,但我認為這會使代碼總體上不那么清晰。 至少通過這種方式,你可以跟隨你從現在起三個月后的所作所為......

st = '''
<!-- info mp3 here -->
                            192 kbps<br />2:41<br />3.71 mb  </div>
<!-- info mp3 here -->
                            3.49 mb  </div>
<!-- info mp3 here -->
                            128 kbps<br />3:31<br />3.3 mb   </div>
'''

p = re.findall(r'<!-- info mp3 here -->\s+(.*?)\s+</div>',st)
p2 = [row.split('<br />') for row in p]
p3 = [[None]*(3 - len(row)) + row for row in p2]

>>> p3
[['192 kbps', '2:41', '3.71 mb'], [None, None, '3.49 mb'], ['128 kbps', '3:31', '3.3 mb']]

並且,根據字符串的可變性,您可能希望編寫一個更通用的清除函數,即條帶,大小寫等等,並將其映射到您提取的每個項目。

這是一個正則表達式解決方案,通過更具體的工作。 我不確定這比卡梅爾的回答更可取,但我想我會按照要求回答這個問題。 而不是返回None ,前兩個可選組返回空字符串'' ,我認為它可能足夠接近。

請注意嵌套的組結構。 前兩個外部組是可選的,但<br />標記是他們匹配所必需的。 這樣,如果少於兩個<br />標簽,則最后一項在結束前不匹配:

rx = r'''<!--\ info\ mp3\ here\ -->\s+   # verbose mode; escape literal spaces
         (?:                             # outer non-capturing group  
            ([^<>]*)                     # inner capturing group without <>
            (?:<br\ />)                  # inner non-capturing group matching br
         )?                              # whole outer group is optional
         (?:                             
            ([^<>]*)                     # all same as above
            (?:<br\ />)                
         )?
         (?:                             # outer non-capturing group
            (.*?)                        # non-greedy wildcard match
            (?:\s+</div>)                # inner non-capturing group matching div
         )'''                            # final group is not optional

測試:

>>> re.findall(rx, st, re.VERBOSE)
[('192 kbps', '2:41', '3.71 mb'), 
 ('', '', '3.49 mb'), 
 ('128 kbps', '3:31', '3.3 mb')]

請注意re.VERBOSE標志,除非您刪除上面的所有空格和注釋,否則這是必需的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM