2

そこで、Python スクリプトで、「1991 年 1 月 26 日」という形式の日付を含むテキスト ファイルを開きます。

これが私の正規表現です:

pattern = """
(?:(September|April|June|November),\ (0?[1-9]|[12]\d|30),\ ((?:19|20)\d\d))#Months   with 30 days
|(?:(January|March|May|July|August|October|December),\ (0?[1-9]|[12]\d|3[01]),\ ((?:19|20)\d\d))#Months with 31 days
|(?:February, (?:(?:(0?[1-9]|1\d|2[0-8]),\ ((?:19|20)\d\d))|(?:(29),\ ((?:(?:19|20)(?:04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96))|2000))))#February with 28 days or 29 with a leap year
"""

r = re.compile(pattern, re.VERBOSE)

この正規表現は、うるう年の 2 月 29 日を含む実際の日付と一致する必要があります。

私が抱えている問題は、開いているテキスト ファイルを調べて、一致するすべての日付をリストに入れる方法を考え出すことです。.match、.search、.split などを使用してみましたが、うまくいきませんでした。リストを別のリストと簡単に比較して、両方のリストにあるすべての日付を見つけることができるように、すべての一致を文字列としてリストに入れる方法はありますか? 基本的に私はリストが次のように出てくることを望みます

[「1990 年 1 月 1 日」、「2012 年 2 月 29 日」、「1945 年 12 月 25 日」、...]

また、私が持っている正規表現が正しいかどうか教えてください。別の質問への回答から変更しましたが、テキスト ファイルの日付が一致しているかどうかを確認できないため、正しいかどうかわかりません。

4

3 に答える 3

3

re.findall()あなたが試したことのリストに言及していませんでした。これにより、すべての正規表現一致のリストが得られます。

ただし、すべての非キャプチャ グループを使用する必要があります。そう(?:...)しないと、一致したすべてのグループのリストが取得されます(...)。したがって、私は提案します

pattern = """
    (?:September|April|June|November)
    ,[ ] 
    (?:0?[1-9]|[12]\d|30)
    ,[ ]
    (?:19|20)\d\d # Months with 30 days

    |

    (?:January|March|May|July|August|October|December)
    ,[ ] 
    (?:0?[1-9]|[12]\d|3[01])
    ,[ ] 
    (?:19|20)\d\d # Months with 31 days

    |

    February
    ,[ ] 
    (?:
     (?:0?[1-9]|1\d|2[0-8])
     ,[ ] 
     (?:19|20)\d\d
    |
     29
     ,[ ] 
     (?:
      (?:19|20)
      (?:04|08|12|16|20|24|28|32|36|40|44|48|
         52|56|60|64|68|72|76|80|84|88|92|96)
     |
      2000
     )
    ) # February with 28 days or 29 with a leap year"""

しかし、日付の正確性を本当に検証する必要があるのでしょうか? データに偽の日付が表示されることを期待していFebruary, 31, 2000ますか? そうでない場合は、正規表現を大幅に簡素化できます。または、少なくとも、巨大な正規表現よりもこのタスクに適した日付解析関数に日付検証を委任します。

例えば:

pattern = """
    (?:January|February|March|April|May|June|
       July|August|September|October|November|December)
    ,[ ]
    [0-3]?\d
    ,[ ]
    (?:19|20)\d\d
"""

January, 0, 1999orのようなナンセンスに一致February, 31, 2000しますが、それは本当に重要でしょうか?

于 2012-04-25T05:54:02.490 に答える
1

単純な正規表現を使用して前処理し、datetime.strptime()関数を使用して日付を検証できます。

import re
from datetime import datetime

def extract_date_strings(text):
    return filter(valid_date, re.findall(r"[A-Z][a-z]+, \d\d?, \d{4}", text))

def valid_date(datestr):
    try:
        return datetime.strptime(datestr, "%B, %d, %Y") #note: locale dependent
    except ValueError: 
        return None

このコードを使用して、結果をテスト用のコードと比較できます。

print extract_date_strings('''"January, 1, 1990", "February, 29, 2012",
     "December, 25, 1945"
     May, 40, 1945 Not a Month, 20, 1945
     February, 29, 2000 February, 29, 1900
     May, 1, 199
     ''')

出力

['January, 1, 1990', 'February, 29, 2012', 'December, 25, 1945', 
 'February, 29, 2000']
于 2012-09-16T09:29:06.353 に答える
0

ランダムな熟考:

正規表現が正しいかどうかを尋ねる必要がある場合、それは複雑すぎます。

re.VERBOSE の考え方は、正規表現を読みやすくすることであり、いずれにしても隠されている明白なコメントを追加することではありません。SO 水平スクロール バーが表示される場合は、ガフが長すぎます。

存在しない場合は、次の出現箇所を特定するためにfindall使用するループを作成し、次の引数に使用できます。searchmatch_object.end()possearch

def myfindall(regex, strg):
    alist = []
    pos = 0
    while True:
        m = regex.search(strg, pos)
        if not m: break
        alist.append(m.group(0))
        pos = m.end()
    return alist

月の名前の後にカンマが必要ですか?

于 2012-04-25T06:39:38.567 に答える