我编写了一个带有以下函数的python脚本,该脚本将包含多个日期的文件名作为输入。
CODE
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'))
输出
返回:2012年 - 我希望这是2009年(即字符串中最后一次出现的年份)
返回:2012年 - 这是正确的! (最后一次出现的年份是第一次,因此是正确的)
返回:2001年 - 我希望这是1968年(即最后一次出现在字符串中)
问题
可以看出,正则表达式只会针对一年的第一次出现而不是最后一次出现。这是有问题的,因为有些标题(例如此处包含的标题)以一年开头。
搜索了获得年度最后一次出现的方法后,我找到了negative lookahead,last occurrence of repeated group和last 4 digits in URL等资源,这些资源都没有让我更接近实现期望的结果。目前没有任何问题可以回答这个独特的案例。
预期成果
答案 0 :(得分:2)
根据@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 :(得分:1)
您需要更改两件事:
.*?
懒惰模式必须转为贪婪.*
(在这种情况下,.*
之后的子模式将与字符串中的最后一个匹配)请参阅this demo:
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)
答案 2 :(得分: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'))