在python中查找正则表达式的第二个匹配的索引

时间:2015-05-19 14:02:32

标签: python regex python-3.x

所以我试图重命名文件以匹配plex mediaserver的命名约定。 (SxxEyy)

现在我有大量使用例如的文件。 411为S04E11。我编写了一个小函数,它将搜索此模式的出现并将其替换为正确的约定。像这样:

pattern1 = re.compile('[Ss]\\d+[Ee]\\d+')
pattern2 = re.compile('[\.\-]\d{3,4}')

def plexify_name(string):
    #If the file matches the pattern we want, don't change it
    if pattern1.search(string):
        return string
    elif pattern2.search(string):
        piece_to_change = pattern2.search(string)
        endpos = piece_to_change.end()
        startpos = piece_to_change.start()
        #Cut out the piece to change
        cut = string[startpos+1:endpos-1]
        if len(cut) == 4:
            cut = 'S'+cut[0:2] + 'E' + cut[2:4]
        if len(cut) == 3:
            cut = 'S0'+cut[0:1] + 'E' + cut[1:3]
        return string[0:startpos+1] + cut + string[endpos-1:]

这非常有效。但事实证明,一些文件名将在其中有一年,例如。 the.flash.2014.118.mp4在这种情况下,它将改变2014年。

我尝试使用

pattern2.findall(string)

这会返回一个像这样的字符串列表 - > [' .2014',' .118']但我想要的是一个匹配对象列表,所以我可以检查是否有2,在这种情况下使用第二个的开始/结束。我似乎无法在re文档中找到一些可以做到的事情。我错过了什么或者我需要采取完全不同的方法吗?

1 个答案:

答案 0 :(得分:1)

您可以尝试将匹配锚定到文件扩展名:

pattern2 = re.compile(r'[.-]\d{3,4}(?=[.]mp4$)')

在这里,(?= ... )是一个前瞻性断言,意味着必须存在正则表达式匹配的东西,但它不是匹配的一部分:

>>> pattern2.findall('test.118.mp4')
['.118']
>>> pattern2.findall('test.2014.118.mp4')
['.118']
>>> pattern2.findall('test.123.mp4.118.mp4')
['.118']

当然,您希望它能够与所有可能的扩展一起使用:

>>> p2 = re.compile(r'[.-]\d{3,4}(?=[.][^.]+$)')
>>> p2.findall('test.2014.118.avi')
['.118']
>>> p2.findall('test.2014.118.mov')
['.118']

如果剧集编号和扩展名之间有更多内容,匹配的正则表达式开始变得棘手,所以我建议使用非正则表达式处理它:

>>> f = 'test.123.castle.2014.118.x264.mp4'
>>> [p for p in f.split('.') if p.isdigit()][-1]
'118'

或者,您可以使用finditer获取所有匹配项的匹配对象,并通过将迭代器转换为列表来扩展迭代器:

>>> p2 = re.compile(r'[.-]\d{3,4}')
>>> f = 'test.2014.712.x264.mp4'
>>> matches = list(p2.finditer(f))
>>> matches[-1].group(0)
'.712'