Извлечь неправильно отформатированную дату из строки (разбор даты, НЛП)
У меня есть большой список файлов, некоторые из которых имеют даты, встроенные в имя файла. Формат дат является непоследовательным и часто неполным, например, "Aug06", "Aug2006", "August 2006", "08-06", "01-08-06", "2006", "011004" и т. Д. Кроме того к тому же, некоторые имена файлов имеют несвязанные числа, которые выглядят как даты, например, "20202010".
Короче говоря, даты, как правило, неполные, а иногда и отсутствуют, неправильно форматируются и встраиваются в строку с другой информацией, например, "Report Aug06.xls".
Существуют ли какие-либо модули Perl, которые будут достаточно хорошо угадывать дату по такой строке? Это не обязательно должно быть на 100% правильно, так как это будет проверено человеком вручную, но я пытаюсь максимально упростить этот процесс, и есть тысячи записей для проверки:)
3 ответа
Date::Parse определенно будет частью вашего ответа - бит, который обрабатывает произвольно отформатированную строку, похожую на дату, и делает из нее фактическую пригодную для использования дату.
Другая часть вашей проблемы - остальные символы в ваших именах файлов - достаточно необычна, так что вы вряд ли найдете кого-то, кто упаковал модуль для вас.
Не видя больше ваших образцов данных, на самом деле можно только догадываться, но я бы начал с определения возможных или вероятных кандидатов в "секцию дат".
Вот неприятный пример грубой силы, использующий Date::Parse (более разумный подход будет использовать список регулярных выражений для определения идентификаторов битов дат - я с удовольствием записываю циклы ЦП, хотя и не думаю, что все так сложно!)
!/usr/bin/perl
use strict;
use warnings;
use Date::Parse;
my @files=("Report Aug06.xls", "ReportAug2006", "Report 11th September 2006.xls",
"Annual Report-08-06", "End-of-month Report01-08-06.xls", "Report2006");
# assumption - longest likely date string is something like '11th September 2006' - 19 chars
# shortest is "2006" - 4 chars.
# brute force all strings from 19-4 chars long at the end of the filename (less extension)
# return the longest thing that Date::Parse recognises as a date
foreach my $file (@files){
#chop extension if there is one
$file=~s/\..*//;
for my $len (-19..-4){
my $string = substr($file, $len);
my $time = str2time($string);
print "$string is a date: $time = ",scalar(localtime($time)),"\n" if $time;
last if $time;
}
}
http://search.cpan.org/perldoc?DateTime::Format::Natural выглядит как кандидат на эту работу. Я не могу ручаться за это лично, но у него есть хорошие отзывы.