2010-08-10 25 views
6

Mam dużą listę plików, z których niektóre mają daty osadzone w nazwie pliku. Format dat jest niespójny i często niekompletny, np. "Aug06", "Aug2006", "August 2006", "08-06", "01-08-06", "2006", "011004" itd. Poza tym niektóre nazwy plików mają niepowiązane numery, które wyglądają nieco jak daty, np "20202010".Wyodrębnij niekonsekwentnie sformatowaną datę z ciągu znaków (analiza daty, NLP)

W skrócie, daty są zwykle niekompletne, czasami nie istnieją, są niespójnie sformatowane i są osadzone w ciągu znaków z innymi informacjami, np. "Zgłoś Aug06.xls".

Czy są dostępne jakieś moduły Perla, które wykonają przyzwoitą pracę zgadując datę z takiego ciągu? To nie musi być w 100% poprawne, ponieważ będzie ono weryfikowane ręcznie przez człowieka, ale staram się, aby rzeczy były tak proste, jak to tylko możliwe dla tej osoby i są tysiące wpisów do sprawdzenia :)

Odpowiedz

3

Data :: Parse z pewnością będzie częścią twojej odpowiedzi - bitem, który wypracowuje losowo sformatowany ciąg datkowy i sprawi, że data rzeczywistego użytku będzie poza nim.

Inna część problemu - pozostałe znaki w nazwach plików - jest dość niezwykła, ponieważ prawdopodobnie nie znajdziesz kogoś, kto przygotował dla ciebie moduł.

Nie widząc więcej próbek danych, można tylko zgadywać, ale zacznę od zidentyfikowania możliwych lub prawdopodobnych kandydatów z sekcji "daty".

Oto nieprzyjemny przykład brutalnej siły przy użyciu funkcji Date :: Parse (mądrzejszy sposób użyłby listy regex-en do wypróbowania i określenia dat-bitów - cieszę się, że mogę wypalać cykle procesora, aby nie myśleć tak bardzo !)

!/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; 
    } 
    } 
+0

To jest trochę podobne do tego, jak to zrobiłem na końcu, ale moje jest znacznie dłuższe, brzydsze i przerażające :) Pozostawię pytanie otwarte na razie, na wypadek, gdyby ktoś wcześniej natknął się na problem, ale wydaje się, że lubię trochę przewijać własne rozwiązanie ... –

+0

Twoja odpowiedź jest zasadniczo poprawna; wydaje się, że nie ma tam żadnych bibliotek, musisz to zrobić samemu :) –

0

Date::Parse robi to, co chcesz.

+0

Data :: Parse nie ładnie radzi sobie z pozostałymi śmieciami, więc mam za to 100% niezdefiniowaną szybkość; Potrzebuję czegoś na tyle sprytnego, by zignorować crud i znaleźć randkę. Jest to, jak sądzę, tyle samo przetwarzania języka naturalnego, co przetwarzanie daty. –

0

DateTime::Format::Natural wygląda jak kandydat do tej pracy. Nie mogę ręczyć za to osobiście, ale ma ona good reviews.

+0

Zrobiłem to, ale tak jak Date :: Parse, Date :: Manip et al wydaje się wymagać, aby wszystkie dane w ciąg ma związek z datą, podczas gdy większość treści moich napisów jest po prostu szumem (innymi częściami nazwy pliku). –

Powiązane problemy