簡體   English   中英

在 Python 中使用正則表達式提取 substring

[英]Extracting substring with alternatives using regex in Python

我試着尋找以前的帖子,但找不到任何與我正在尋找的完全匹配的帖子,所以就到這里吧。

我正在嘗試解析 dataframe 中的字符串,並在找到匹配項時捕獲某個 substring(年份)。 格式可能會有很大差異,我想出了一種不太優雅的方法來完成它,但我想知道是否有更好的方法。

字符串可以看起來像這樣

Random Text 31.12.2020
1.1. -31.12.2020
010120-311220
31.12.2020
1.1.2020-31.12.2020 -
1.1.2019 - 31.12.2019
1.1. . . 31.12.2019 -
1.1.2019 - -31.12.2019
010120-311220 other random words

我正在尋找年份,目前是通過查找最后日期及其年份。 當前的正則表達式是.+3112(\d{2,4})|.+31\.12\.(\d{2,4})其中

它將在010120-311220的組 1 中返回 20,在1.1.2020-31.12.2020 -的組 2 中返回 2020

問題是我無法事先知道匹配將屬於哪個組,因為在第一個示例中,第 2 組不存在,而在第二個示例中,當使用re.match(regexPattern, stringOfInterest)時,第 1 組將返回 None 。 因此,我無法通過在匹配項 object 上天真地使用.group(1)來訪問該值,因為有時該值會在.group(2)中。

到目前為止我想出的最好的方法是用(?P<groupName>\d{2,4)命名組並檢查 Nones

def getYear(stringOfInterest):
    regexPattern = '(^|.+)3112(?P<firstMatchType>\d{2,4})|(^|.+)31\.12\.(?P<secondMatchType>\d{2,4})'
    matchObject = re.match(regexPattern, stringOfInterest)
    if matchObject is not None:
        matchDict = matchObject.groupdict()
        if matchDict['firstMatchType'] is not None:
            return matchDict['firstMatchType']
        else:
            return matchDict['secondMatchType']
    return None

import re
df['year'] = df['text'].apply(getYear)

雖然這行得通,但直覺上這似乎是一種愚蠢的做法。 有任何想法嗎?

看起來你所有的歲月都來自二十一世紀 在這種情況下,您只需要

df['year'] = '20' + df['text'].str.extract(r'.*31\.?12\.?(?:\d{2})?(\d{2})', expand=False)

請參閱正則表達式演示 詳情

  • .* - 盡可能多的除換行符以外的任何零個或多個字符
  • 31\.?12\.? - 31 ,一個可選的. , 12和一個可選的. 字符
  • (?:\d{2})? - 可選的兩位數序列
  • (\d{2}) - 第 1 組:年份的最后兩位數字。

看一個 Pandas 測試:

import pandas as pd
df = pd.DataFrame({'text': ['Random Text 31.12.2020','1.1. -31.12.2020','010120-311220','31.12.2020','1.1.2020-31.12.2020 -','1.1.2019 - 31.12.2019','1.1. . . 31.12.2019 -','1.1.2019 - -31.12.2019','010120-311220 other random words']})
df['year'] = '20' + df['text'].str.extract(r'.*31\.?12\.?(?:\d{2})?(\d{2})', expand=False)

Output:

>>> df
                               text  year
0            Random Text 31.12.2020  2020
1                  1.1. -31.12.2020  2020
2                     010120-311220  2020
3                        31.12.2020  2020
4             1.1.2020-31.12.2020 -  2020
5             1.1.2019 - 31.12.2019  2019
6             1.1. . . 31.12.2019 -  2019
7            1.1.2019 - -31.12.2019  2019
8  010120-311220 other random words  2020

我們可以嘗試在此處對您的輸入列表使用re.findall ,並使用涵蓋兩種變體的正則表達式交替:

inp = ["Random Text 31.12.2020", "1.1. -31.12.2020", "010120-311220", "31.12.2020", "1.1.2020-31.12.2020 -", "1.1.2019 - 31.12.2019", "1.1. . . 31.12.2019 -", "1.1.2019 - -31.12.2019", "010120-311220 other random words"]
output = [re.findall(r'\d{1,2}\.\d{1,2}\.(\d{4})|\d{4}(\d{2})', x)[-1] for x in inp]
output = [x[0] if x[0] else x[1] for x in output]
print(output)  # ['2020', '2020', '20', '2020', '2020', '2019', '2019', '2019', '20']

這里的策略是匹配兩個日期變體中的任何一個。 我們保留每個輸入的最后一個匹配項。 然后,我們使用列表理解來查找非空值。 請注意,有兩個捕獲組,因此只有一個會匹配。

通過僅對日期開始的交替進行分組,您的正則表達式可以分解很多; 這消除了檢查兩組的需要:

regexPattern = r'(?:^|.+)(?:3112|31\.12\.)(?P<year>\d{2,4})'

提取組后,可以將其標准化為適當的四位數年份:

if matchObject is not None:
    return ('20' + matchObject.group('year'))[-4:]

總而言之,我們得到:

import re

def getYear(stringOfInterest):
    regexPattern = r'(?:^|.+)(?:3112|31\.12\.)(?P<year>\d{2,4})'
    matchObject = re.match(regexPattern, stringOfInterest)
    if matchObject is not None:
        return ('20' + matchObject.group('year'))[-4:]
    return None

df['year'] = df['text'].apply(getYear)

這是我解決你問題的方法,也許會有用


import re
string = '''
Random Text 31.12.2020
1.1. -31.12.2022
010120-311220
31.12.2020
1.1.2020-31.12.2018 -
1.1.2019 - 31.12.2019
1.1. . . 31.12.2019 -
1.1.2019 - -31.12.2019
010120-311220 other random words'''
pattern = r'\d{1,2}\.\d{1,2}\.(\d{4})|\d{4}(\d{2})'
matches = re.findall(pattern, string)
print("1) ", matches)

# convert tuple to list
match_array = [i for sub in matches for i in sub]
print(match_array)

#Remove multiple empty spaces from string List
res = [element for element in match_array if element.strip()]
print(res)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM