Извлечь неправильно отформатированную дату из строки (разбор даты, НЛП)

У меня есть большой список файлов, некоторые из которых имеют даты, встроенные в имя файла. Формат дат является непоследовательным и часто неполным, например, "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;
    }
  }

Date::Parse делает то, что вы хотите.

http://search.cpan.org/perldoc?DateTime::Format::Natural выглядит как кандидат на эту работу. Я не могу ручаться за это лично, но у него есть хорошие отзывы.

Другие вопросы по тегам