2010-11-11 21 views
0

Problème: Je dois extraire des données des journaux d'authentification pendant env. 30 emplacements. Les journaux sont au format CSV. Pour que l'analyse soit utile, les entrées de journal doivent correspondre aux heures d'exploitation des emplacements. Les données sont stockées dans des répertoires nommés pour la période couverte par les données: par exemple, data/juin1-juin30 /. Les fichiers CSV sont simplement nommés avec le code d'emplacement , par exemple, LOC1.csv, LOC2.csv. Voici un exemple d'un journal typique:Perl: "problème de journaux bruyants" Création d'un tableau de requêtes regex à partir de plusieurs tableaux/hachages

2010-06-01, 08:30:00 , 0 
2010-06-01, 09:30:00 , 1 
2010-06-01, 10:30:00 , 10 
2010-06-01, 11:30:00 , 7 
2010-06-01, 12:30:00 , 8 
2010-06-01, 13:30:00 , 6 
2010-06-01, 14:30:00 , 3 
2010-06-01, 15:30:00 , 8 
2010-06-01, 16:30:00 , 11 

Les entrées indiquent le nombre de sessions authentifiées avec succès au cours de la période indiquée dans le 3ème champ. Les journaux représentent 24 heures de données qui sont inutiles pour l'analyse puisque les heures d'ouverture diffèrent d'un endroit à l'autre. Le problème maintenant devient comment tirer seulement les données qui correspondent aux heures d'opération. L'analyse doit montrer que l'activité pour les heures d'ouverture est utile. J'ai décidé de créer un fichier de configuration en utilisant YAML avec des tableaux/hachages pour chaque emplacement.

par exemple.,

- branch: headquarters 
    abbrev: HQ 
    months: [04, 06] 
    DOW: [M, T, W, Th] 
    hours: 
     M:    [12, 13, 14, 15, 16, 17, 18] 
     T:    [12, 13, 14, 15, 16, 17, 18] 
     W:  [09, 10, 11, 12, 13, 14, 15, 
         16, 17, 18] 
     Th:  [12, 13, 14, 15, 16, 17, 18, 
         19, 20] 

La désignation mois montre les mois les plus actifs, comme c'est nous soucions tout.

où je suis Le code trouverez les répertoires appropriés en utilisant le tableau mois, il tire les fichiers CSV corrects à l'aide du tableau SIGLE. J'ai donc les fichiers dont j'ai besoin stockés dans un tableau @files. Ma question se résume à concevoir. Les résultats doivent correspondre aux dates appropriées pour chaque mois. Les lundis, mardis ... etc. Est-ce que je crée des tableaux mois stockant les dates pour chaque jour de la semaine? Je suis coincé et je ne sais pas où aller à partir d'ici.

Pour clarifier: Le code tire déjà les fichiers corrects et les charge dans un tableau (en utilisant globbing et Find :: File) pour chaque branche. La question est maintenant d'itérer à travers le tableau @files pour chaque branche et de tirer l'info.

EDIT: sur demande: Je vais mettre du code. C'est la marchandise pour obtenir ces fichiers par les mois indiqués dans le hachage. C'est la partie facile.

foreach my $branch (@$config) { 
     my $name = $branch->{'branch'}; 
     my $months = $branch->{'months'}; 
     my $abbrev = $branch->{'abbrev'}; 

     # find directories for busy months, load in @dirs 
     my @dirs;  
     foreach my $month (@$months) { 
       my $regex2 = qr(stats_2010-$month.*); 
       map { push(@dirs, $_) if $_ =~ $regex2 } @stats_dir; 
     } 

     # find csv files within directories, load in @files 
     my @files; 
     find(\&wanted, @dirs); 
     sub wanted { 
       push(@files, $_) if $_ =~ /$abbrev\.csv/; 
     } 

Sortie: La sortie J'espère obtenir est: Les lignes de chaque fichier représentant les heures de fonctionnement de cette branche. Je pense qu'ils pourraient être sortis dans un fichier séparé par souci de simplicité. Et dans le même format. Ce qui le rend difficile, c'est que vous devez faire correspondre les lundis, mardis, etc. avec des dates en quelque sorte. Cela est dû à différentes heures de fonctionnement pour différents jours. Est-ce que je rends le problème plus difficile que nécessaire? Je me suis assis avec cela trop longtemps et j'espère un nouvel ensemble d'yeux pour me redresser. Mon Perl est OK, mais j'ai besoin d'aide dans le département design/algorithm. Je peux comprendre comment le perlifier, je pense. Mais n'hésitez pas à poster Perl. J'aime lire bon Perl!

Finalement, je vais faire la moyenne de l'activité pour les lundis, mardis ... etc. de chaque mois.

Merci ~

Bubnoff

+0

Il pourrait aider à nous montrer une partie de votre code déjà, et expliquer la sortie dont vous avez besoin. – dlamblin

+0

Posté la partie principale du code. Utilisation de YAML pour la configuration @stats_dir est un tableau de répertoires globbed. – Bubnoff

+0

Voir ci-dessous pour la solution en utilisant la suggestion de dlamblin. – Bubnoff

Répondre

0

Convertissez le jour de la semaine en un nombre lorsque lundi est 1 et dimanche est 7. Ensuite, créez un hachage qui ressemble à 1=>{12=>1,13=>1,14=>1,15=>1,16=>1,17=>1,18=>1},2=>{12=>1,13=>1,14=>1,15=>1,16=>1,17=>1,18=>1},... (remarquez comment DOW dans votre YAML est redondant).

jusqu'à présent:

use DateTime; 
foreach $file (@files) { 
    open F "<$file"; 
    foreach $line (<F>) { 
    $line =~ m/^(\d+)-(\d+)-(\d+), (\d+):(\d+):(\d+) , (\d+)/; 
    $dt = DateTime->new(year => $1, 
         month => $2, 
         day => $3, 
         hour => $4, 
         minute => $5, 
         second => $6, 
         ); 
    $count = $7; #Possibly redundant; Use it if you're aggregating. 
    if (exits $selection{$dt->day_of_week} 
    && exists $selection{$dt->day_of_week}{$dt->hour}) { 
     print $line; 
    } 
    } 
} 
+0

Je vois où vous allez. Je vais essayer ceci et revenir plus tard. Merci! – Bubnoff

+0

Ahem ... Mec, tu baises !! Mise à jour du code ci-dessus. – Bubnoff

0

Il y a des modules qui vous donnera le dow de la date et l'heure que vous avez, mais si elles sont trop lourds vous le pouvez use Time::Local. Parse la date - vous devrez le faire de toute façon je pense - sur chaque ligne et le nourrir à travers timelocal, puis à travers localtime qui vous donnera le dow. Vous devrez masser $ mon et $ year de façon appropriée.

$dow = (localtime(timelocal(0, 0, 0, $mday, $mon, $year)))[6]; 

Une fois que vous avez la dot pour l'entrée, vous saurez quoi en faire.

+0

Merci, je vais vérifier cela. Cela simplifierait les choses. – Bubnoff

1

La solution que je utilise est de dlamblin (Merci encore pour votre aide !!).

Voici le config YAML ajusté:

- branch: Headquarters 
    abbrev: HQ 
    months: [04, 06] 
    DOW: 
     1: {12: 1, 13: 1, 14: 1, 15: 1, 
      16: 1, 17: 1, 18: 1} 
     2: {12: 2, 13: 2, 14: 2, 15: 2, 
      16: 2, 17: 2, 18: 2} 
     3: {09: 3, 10: 3, 11: 3, 12: 3, 
      13: 3, 14: 3, 15: 3, 16: 3, 17: 3, 18: 3} 
     4: {12: 4, 13: 4, 14: 4, 15: 4, 16: 4, 
      17: 4, 18: 4, 19: 4, 20: 4} 

Voici le Perl:

foreach my $dir (@dirs) { 
    my $file = qq($dir/$abbrev.csv); 
    open(F, $file); 
    my @data=<F>; 
    foreach my $line (@data) { 
     chomp($line); 
     unless ($line =~ m/^(\d+)-(\d+)-(\d+), (\d+):(\d+):(\d+) , (\d+)/){next;} 
     my $dt = DateTime->new(year => $1, 
           month => $2, 
           day => $3, 
           hour => $4, 
           minute => $5, 
           second => $6, 
           ); 
     my $count = $7; 
     if (exists $DOW{$dt->day_of_week} && exists $DOW{$dt->day_of_week}{$dt->hour}) { 
      print $line . "\n"; 
     } 
    } 
    close(F); 
} 
+0

Vous êtes les bienvenus. – dlamblin