繁体   English   中英

正则表达式匹配字符串中的最后一次出现

[英]Regular expression match last occurence of year in string

我编写了一个带有以下函数的python脚本,该脚本将包含多个日期的文件名作为输入。

import re
from datetime import datetime

def ExtractReleaseYear(title):
    rg = re.compile('.*?([\[\(]?((?:19[0-9]|20[01])[0-9])[\]\)]?)', re.IGNORECASE|re.DOTALL)
    match = rg.search(title) # Using non-greedy match on filler
    if match:
        releaseYear = match.group(1)
        try:
            if int(releaseYear) >= 1900 and int(releaseYear) <= int(datetime.now().year) and int(releaseYear) <= 2099: # Film between 1900-2099
                return releaseYear
        except ValueError:
            print("ERROR: The film year in the file name could not be converted to an integer for comparison.")
            return ""

print(ExtractReleaseYear('2012.(2009).3D.1080p.BRRip.SBS.x264'))
print(ExtractReleaseYear('Into.The.Storm.2012.1080p.WEB-DL.AAC2.0.H264'))
print(ExtractReleaseYear('2001.A.Space.Odyssey.1968.1080p.WEB-DL.AAC2.0.H264'))

OUTPUT

返回:2012年 - 我希望这是2009年(即字符串中最后一次出现的年份)

退回:2012年 - 这是正确的! (最后一次出现的年份是第一次,因此正确)

返回:2001年 - 我希望这是1968年(即字符串中最后一次出现的年份)

问题

可以看出,正则表达式只会针对一年的第一次出现而不是最后一次出现。 这是有问题的,因为有些标题(例如此处包含的标题)以一年开头。

在寻找获得年度最后一次出现的方法之后,我得到了这样的资源,如负面预测重复组的最后一次出现以及URL中的最后4位数 ,这些都没有让我更接近达到预期的结果。 目前没有任何问题可以回答这一独特案例

预期结果

  • 我想从给定的文件名中提取一年中的LAST事件(而不是第一个),并使用上面输出引用中所述的现有定义/函数返回它。 虽然我使用了在线正则表达式引用,但我是regex的新手,并希望有人向我展示如何实现此过滤器来处理上面的文件名。 干杯伙计们。

根据@kenyanke的回答,选择findall()不是search()将是一个更好的选择,因为前者返回所有非重叠的匹配模式。 您可以选择最后匹配的模式作为releaseYear 这是我的正则表达式找到releaseYear

rg = re.compile(r'[^a-z](\d{4})[^a-z]', re.IGNORECASE)
match = rg.findall(title)
if match:
        releaseYear = match[-1]

上面的正则表达式是假设在releaseYear之前或之后的立即字母是非字母字符。 三个字符串的结果( match )是

['2009']
['2012']
['1968']

您需要更改两件事:

  1. 第一个.*? 惰性模式必须转为贪婪.* (在这种情况下, .*之后的子模式将与字符串中的最后一个匹配)
  2. 您需要使用的组是第2组,而不是第1组(因为它是存储年份数据的组)。 或者使第一个捕获组不捕获。

这个演示

rg = re.compile('.*([\[\(]?((?:19[0-9]|20[01])[0-9])[\]\)]?)', re.IGNORECASE|re.DOTALL)
...
releaseYear = match.group(2)

要么:

rg = re.compile('.*(?:[\[\(]?((?:19[0-9]|20[01])[0-9])[\]\)]?)', re.IGNORECASE|re.DOTALL)
...
releaseYear = match.group(1)

考虑在search()上使用findall()?

它会将所有值从左到右放入列表中,只需访问最右边的值即可得到您想要的值。

import re
from datetime import datetime

def ExtractReleaseYear(title):
    rg = re.compile('.*?([\[\(]?((?:19[0-9]|20[01])[0-9])[\]\)]?)', re.IGNORECASE|re.DOTALL)
    match = rg.findall(title)

    if match:
        try:
            releaseYear = match[-1][-1]
            if int(releaseYear) >= 1900 and int(releaseYear) <= int(datetime.now().year) and int(releaseYear) <= 2099: # Film between 1900-2099
                return releaseYear
        except ValueError:
            print("ERROR: The film year in the file name could not be converted to an integer for comparison.")
            return ""

print(ExtractReleaseYear('2012.(2009).3D.1080p.BRRip.SBS.x264'))
print(ExtractReleaseYear('Into.The.Storm.2012.1080p.WEB-DL.AAC2.0.H264'))
print(ExtractReleaseYear('2001.A.Space.Odyssey.1968.1080p.WEB-DL.AAC2.0.H264'))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM