Python 正则表达式中的条件匹配

Python 正则表达式中的条件匹配,python,regex,Python,Regex,我正在尝试从下面给定的字符串中提取一些信息 >>> st = ''' ... <!-- info mp3 here --> ... 192 kbps<br />2:41<br />3.71 mb </div> ... <!-- info mp3 here --> ... 3.49 mb </div&

我正在尝试从下面给定的字符串中提取一些信息

>>> 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>
... '''
>>>
因此,我的问题是如何更改我上面的
regex
以匹配所有条件。我相信我当前的regex严格依赖于

标记,那么我如何使其有条件


我知道我不应该使用正则表达式来解析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']]
st=''
192kbps
2:41
3.71MB 3.49 mb 128kbps
3:31
3.3MB ''' p=re.findall(r'\s+(.*)\s+',st) p2=[p中的行的行分割('
')] p3=[[None]*(3-列(行))+p2中的行对应行] >>>p3 [192kbps',2:41',3.71mb'],[None,None',3.49mb'],[128kbps',3:31',3.3Mb']

而且,根据字符串中的可变性,您可能希望编写一个更通用的清理函数,用于剥离、装箱等,并将其映射到您提取的每个项目。

这里有一个正则表达式解决方案,它的工作原理是更具体一点。我不确定这是否比他的答案更可取,但我想我会按要求回答这个问题。前两个可选组没有返回
None
,而是返回空字符串
'
,我认为这可能已经足够接近了

请注意嵌套的组结构。前两个外部组是可选的,但需要使用

标记才能匹配。这样,如果少于两个

标记,则最后一项直到末尾才匹配:

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.VERBOSE
标志,除非删除上面的所有空白和注释,否则该标志是必需的

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']]
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')]