У меня есть текстовый файл с несколькими строками, одна из которых содержит description
поля, и это поле имеет несколько комбинаций или обозначений дат, окруженных другими строками, такими как colasas|04/18/2017|NXP
, FTP Permanent|09|10|2012|FTP
и Project|16 July 2005|Design
. из которого я хочу только разобрать даты. Один из способов, который я нашел, - использовать модуль dateutil
который выглядит сложным и много манипуляций для этой цели.
Поэтому, проходя тест примеров, он работает для определенных комбинаций.
>>> from dateutil.parser import parse
>>> test_cases = ['04/30/2009', '06/20/95', '8/2/69', '1/25/2011', '9/3/2002', '4-13-82', 'Mar-02-2009', 'Jan 20, 1974',
... 'March 20, 1990', 'Dec. 21, 2001', 'May 25 2009', '01 Mar 2002', '2 April 2003', '20 Aug. 2004',
... '20 November, 1993', 'Aug 10th, 1994', 'Sept 1st, 2005', 'Feb. 22nd, 1988', 'Sept 2002', 'Sep 2002',
... 'December, 1998', 'Oct. 2000', '6/2008', '12/2001', '1998', '2002']
>>> for date_string in test_cases:
... print(date_string, parse(date_string).strftime("%Y%m%d"))
...
04/30/2009 20090430
06/20/95 19950620
8/2/69 19690802
----- etc --------
Тем не менее, у меня есть следующая комбинация данных, которую мне нужно разобрать, но, выбирая решение выше, он не может получить результаты.
Поскольку description
является необязательным, поскольку оно может отсутствовать в определенный момент, поэтому я рассмотрел использование (?:description:* (.*))?
,
description: colasas|04/18/2017|NXP
description: colasas|04/18/2017|NXP
description: Remedy Tkt 01212152 Orcad move
description: FTP Permanent|09|10|2012|FTP
description: Remedy Tkt 01212152 Orcad move
description: TDA Drop12 Account|July 2004|TDA Drop12 Account
description: ftp|121210|ftp
description: Design Foundry Project|16 July 2005|Design Foundry Project
description: FTP Permanent|10/10/2010|FTP
description: WFS-JP|7-31-05|WFS-JP
description: FTP Permanent|10|11|2010|FTP
Я повторно сформулировал вопрос. Просто позвольте больше видеть, чтобы получить больше ресурсов.
Ниже приведен сценарий actula, который имеет три разных совпадения dn
, ftpuser
и последнее description
которое я ищу для решения. Ниже скрипт работает для всех совпадений, но последний feild, который представляет собой описание, имеющее смешанные и необработанные данные, из которых мне нужны только даты
"|"
,#!/usr/bin/python3
# ./dataparse.py
from __future__ import print_function
from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE,SIG_DFL)
import re
with open('test2', 'r') as f:
for line in f:
line = line.strip()
data = f.read()
regex = (r"dn:(.*?)\nftpuser: (.*)\ndescription:* (.*)")
matchObj = re.findall(regex, data)
for index in matchObj:
#print(index)
index_str = ' '.join(index)
new_str = re.sub(r'[=,]', ' ', index_str)
new_str = new_str.split()
print("{0:<30}{1:<20}{2:<50}".format(new_str[1],new_str[8],new_str[9]))
Результат:
$ ./dataparse.py
ab02 disabled_5Mar07 Remedy
mela Y ROYALS|none|customer
ab01 Y VGVzdGluZyA
[email protected] T REG-JP|7-31-05|REG-JP
Используемый метод parse
принимает аргумент ключевого слова, позволяющий игнорировать нерелевантные части строки.
:param fuzzy:
Whether to allow fuzzy parsing, allowing for string like "Today is
January 1, 2047 at 8:21:00AM".
Демо-версия:
>>> parse('colasas|04/18/2017|NXP', fuzzy=True)
datetime.datetime(2017, 4, 18, 0, 0)
Существует еще один, который также возвращает кортежи, включая части строки, которые были проигнорированы:
>>> parse('colasas|04/18/2017|NXP', fuzzy_with_tokens=True)
(datetime.datetime(2017, 4, 18, 0, 0), ('colasas|', '|NXP'))
Этот метод не будет работать отлично со всеми вашими входными строками, но он должен получить от вас большую часть пути. Возможно, вам придется сделать предварительную обработку для незнакомых.
text="""
description: colasas|04/18/2017|NXP
description: colasas|04/18/2017|NXP
description: Remedy Tkt 01212152 Orcad move
description: FTP Permanent|09|10|2012|FTP
description: Remedy Tkt 01212152 Orcad move
description: TDA Drop12 Account|July 2004|TDA Drop12 Account
description: ftp|121210|ftp
description: Design Foundry Project|16 July 2005|Design Foundry Project
description: FTP Permanent|10/10/2010|FTP
description: WFS-JP|7-31-05|WFS-JP
description: FTP Permanent|10|11|2010|FTP
"""
import re
reg=re.compile(r"(?ms)\|(\d\d)(\d\d)(\d\d)\||\|(\d{1,2})[\|/\-](\d{1,2})[\|/\-](\d{2,4})\||\|(\d*)\s*(\w+)\s*(\d{4})\|")
dates= [ t[:3] if t[1] else t[3:6] if t[4] else t[6:] for t in reg.findall(text) ]
print(dates)
"""
regexp for |121210| ---> \|(\d\d)(\d\d)(\d\d)\|
for |16 July 2005| ---> \|(\d*)\s*(\w+)\s*(\d{4})\|
for the others ---> \|(\d{1,2})[\|/\-](\d{1,2})[\|/\-](\d{2,4})\|
"""
Output: [('04', '18', '2017'), ('04', '18', '2017'), ('09', '10', '2012'), ('', 'July', '2004'), ('12', '12', '10'), ('16', 'July', '2005'), ('10', '10', '2010'), ('7', '31', '05'), ('10', '11', '2010')]
Получите дату как есть:
reg=re.compile(r"(?ms)\|(\d{6})\||\|(\d{1,2}[\|/\-]\d{1,2}[\|/\-]\d{2,4})\||\|(\d*\s*\w+\s+\d{4})\|")
dates= [ t[0] or t[1] or t[2] for t in reg.findall(text) ]
print(dates)
Output:
['04/18/2017', '04/18/2017', '09|10|2012', 'July 2004', '121210', '16 July 2005', '10/10/2010', '7-31-05', '10|11|2010']
Использование некоторых строковых манипуляций
Демо - версия:
s = """description: colasas|04/18/2017|NXP
description: colasas|04/18/2017|NXP
description: Remedy Tkt 01212152 Orcad move
description: FTP Permanent|09|10|2012|FTP
description: Remedy Tkt 01212152 Orcad move
description: TDA Drop12 Account|July 2004|TDA Drop12 Account
description: ftp|121210|ftp
description: Design Foundry Project|16 July 2005|Design Foundry Project
description: FTP Permanent|10/10/2010|FTP
description: WFS-JP|7-31-05|WFS-JP
description: FTP Permanent|10|11|2010|FTP"""
from dateutil.parser import parse
for i in s.split("\n"):
val = i.split("|", 1) #Split by first "|"
if len(val) > 1: #Check if Date in string.
val = val[1].rpartition("|")[0] #Split by right "|"
print( parse(val, fuzzy=True) )
Выход:
2017-04-18 00:00:00
2017-04-18 00:00:00
2012-07-03 00:00:00
2004-07-03 00:00:00
2010-12-12 00:00:00
2005-07-16 00:00:00
2010-10-10 00:00:00
2005-07-31 00:00:00
2010-07-03 00:00:00
Что касается вашей ошибки datetime, удалите from datetime import datetime
Демо - версия:
import re
import datetime
strh = "description: colasas|04/18/2017|NXP"
match = re.search(r'\d{2}/\d{2}/\d{4}', strh)
date = datetime.datetime.strptime(match.group(), '%m/%d/%Y').date()
print(date)
Я достиг этого через regex
учитывая значения между трубами следующим образом:
"(?:description:* .*\|([0-9]{1,2}[-/]+[0-9]{1,2}[-/]+[0-9]{2,4})\|.*)?"
16 July 2005