簡體   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