Regex для извлечения всех сложных форматов дат из строки в Python - PullRequest
0 голосов
/ 01 июля 2018

У меня есть следующая строка:

 dateEntries = "04-20-2009; 04/20/09; 4/20/09; 4/3/09; Mar 20, 2009; March 20, 2009; Mar. 20, 2009; Mar 20 2009; 20 Mar 2009; 20 March 2009; 2 Mar. 2009; 20 March, 2009; Mar 20th, 2009; Mar 21st, 2009; Mar 22nd, 2009; Feb 2009; Sep 2009; Oct 2010; 6/2008; 12/2009; 2009; 2010"

Здесь я хочу извлечь все упомянутые даты, используя regex. В качестве попытки я написал следующее regex:

import re

regEx = r'(?:\d{1,2}[-/th|st|nd|rd\s]*)?(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z\s,.]*(?:\d{1,2}[-/th|st|nd|rd)\s,]*)?(?:\d{2,4})'

re.findall(regEx, dateEntries)

Я ожидал, что это сработает, но вернет только подмножество дат.

A = ['Mar 20, 2009',
 'March 20, 2009',
 'Mar. 20, 2009',
 'Mar 20 2009',
 '20 Mar 2009',
 '20 March 2009',
 '2 Mar. 2009',
 '20 March, 2009',
 'Mar 20th, 2009',
 'Mar 21st, 2009',
 'Mar 22nd, 2009',
 'Feb 2009',
 'Sep 2009',
 'Oct 2010']

Я не понимаю, почему не возвращаются даты:

B=[04-20-2009; 04/20/09; 4/20/09; 4/3/09; 6/2008; 12/2009; 2009; 2010"]

Я создал regEx, расширив r'(?:\d{1,2}[-\s\/])?(?:\d{1,2}[-\/\s])?(?:\d{2,4})', который хорошо работает для множества B. Но regEx не может произвести A+B

Может ли кто-нибудь помочь в создании регулярного выражения для извлечения всех дат, упомянутых в моем dateEntries?

ПРИМЕЧАНИЕ: Я хочу решить эту проблему, используя только регулярные выражения.

Ответы [ 3 ]

0 голосов
/ 01 июля 2018

Попробуйте Regex:

^(?:\d{1,2}(?:(?:-|/)|(?:th|st|nd|rd)?\s))?(?:(?:(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)(?:(?:-|/)|(?:,|\.)?\s)?)?(?:\d{1,2}(?:(?:-|/)|(?:th|st|nd|rd)?\s))?)(?:\d{2,4})$

Демо

0 голосов
/ 01 июля 2018

Ваш шаблон регулярных выражений полностью нечитаем. Пожалуйста, создайте свой шаблон регулярных выражений с помощью простых строительных блоков. Это сделало бы код более читабельным

import re
import calendar

full_months = [month for month in calendar.month_name if month]
short_months = [d[:3] for d in full_months]
months = '|'.join(short_months + full_months)

sep = r'[.,]?\s+'               # seperator
day = r'\d+'
year = r'\d+'
day_or_year = r'\d+(?:\w+)?'

r = re.compile(rf'(?:{day}{sep})?(?:{months}){sep}{day_or_year}(?:{sep}{year})?')
r.findall(dateEntries)
# ['Mar 20, 2009', 'March 20, 2009', 'Mar. 20, 2009', 'Mar 20 2009', '20 Mar 2009', '20 March 2009', '2 Mar. 2009', '20 March, 2009', 'Mar 20th, 2009', 'Mar 21st, 2009', 'Mar 22nd, 2009', 'Feb 2009', 'Sep 2009', 'Oct 2010']
0 голосов
/ 01 июля 2018

Вам просто не хватает одного ? после группы (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec), чтобы пометить его как ненужное. Кроме того, я добавил + за последние две группы, чтобы убедиться, что регулярное выражение не разбивает даты, например "20 марта 2009", на две разные даты.

Полный код:

import re

regEx = r'(?:\d{1,2}[-/th|st|nd|rd\s]*)?(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)?[a-z\s,.]*(?:\d{1,2}[-/th|st|nd|rd)\s,]*)+(?:\d{2,4})+'

dateEntries = "04-20-2009; 04/20/09; 4/20/09; 4/3/09; Mar 20, 2009; March 20, 2009; Mar. 20, 2009; Mar 20 2009; 20 Mar 2009; 20 March 2009; 2 Mar. 2009; 20 March, 2009; Mar 20th, 2009; Mar 21st, 2009; Mar 22nd, 2009; Feb 2009; Sep 2009; Oct 2010; 6/2008; 12/2009; 2009; 2010"
result = re.findall(regEx, dateEntries)
print(result)

Если ваша дата имеет первые пробелы, результат также будет иметь первые пробелы. Если вы продолжите использовать строку даты, вы можете удалить их, например, с помощью метода .strip()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...