Lire le file, faire correspondre les strings et formater la sortie dans Perl

J'ai passé de longues années à ce sujet et il me fait maintenant mal à ma tête. J'ai simplifié le file de données mais, fondamentalement, j'ai grep'd quelques valeurs sur 5 files différents et je veux maintenant les graver dans Excel. Donc, le format Excel pour un graphique linéaire doit corriger.

Le file actuel ressemble

Report-20140521.csv: Sun, 20 Report-20140530.csv: Sun, 23 Report-20140606.csv: Sun, 24 Report-20140613.csv: Sun, 25 Report-20140621.csv: Sun, 21 Report-20140521.csv: Mon, 22 Report-20140530.csv: Mon, 23 Report-20140606.csv: Mon, 24 Report-20140613.csv: Mon, 24 Report-20140621.csv: Mon, 21 Report-20140521.csv: Tues, 22 Report-20140530.csv: Tues, 23 Report-20140606.csv: Tues, 20 Report-20140613.csv: Tues, 21 Report-20140621.csv: Tues, 21 

Je voudrais aplatir ceci et avoir cinq lignes avec les valeurs dans chacun comme:

  Sun Mon Tue wed .. Report-20140521.csv: 20 22 22 Report-20140530.csv: 23 23 23 Report-20140606.csv: 24 24 20 Report-20140613.csv: 25 24 21 Report-20140621.csv: 21 21 21 

Ont examiné l'utilisation de arrays et de arrays de arrays, mais de toute façon, datatables semblent être truquées et ne peuvent pas l'obturer à l'aide des 5 lignes différentes. En plus de cela, je dois conserver le nom du file, puisqu'il sera rayé dans un format de date plus tard dans Excel.

Je pense qu'un hash de hashes fonctionnerait bien pour cela, puisque vos valeurs de Day of Week sont discrètes et délimitées. Une certaine variante de ceci pourrait fonctionner:

 use ssortingct; my %masortingx; open IN, 'yourfile.txt' or die $!; while (<IN>) { chomp; my ($report, $val) = split /,/; my ($file, $dow) = split /: /, $report; $masortingx{$file}{$dow} = $val; } close IN; my @dow = qw(Sun Mon Tues Wed Thu Fri Sat); foreach my $file (sort keys %masortingx) { print $file, "\t"; my $report_ref = $masortingx{$file}; foreach my $dow (@dow) { print $$report_ref{$dow}, "\t"; } print "\n"; } 

Exemple de sortie:

 Report-20140521.csv 20 22 22 Report-20140530.csv 23 23 23 Report-20140606.csv 24 24 20 Report-20140613.csv 25 24 21 Report-20140621.csv 21 21 21 

Cette solution fait comme vous le requestz. Il utilise des en- %headers de hash %headers pour convertir les noms de dates en numéros de colonne à mesure que datatables sont lues et produit un hachage qui est codé par le nom de file CSV. Les valeurs du hash sont des arrays de paires de valeurs, chaque paire comprenant un nombre de colonne et une valeur pour cette colonne

Une fois que datatables ont été digérées dans le hash, elles sont numérisées dans l'ordre sortingé du nom de file. Un tableau @info est initialisé sur sept champs vides et les paires colonne / valeur dans le hash sont utilisées pour écraser les colonnes fournies

La longueur maximale des noms de file est déterminée et utilisée en premier dans l'printing du tableau de noms de jour @headers , puis le tableau @info pour chaque input de hachage

J'espère que ça aide

 use ssortingct; use warnings; use List::Util 'max'; my $filename = 'current.txt'; open my $fh, '<', $filename or die qq{Unable to open "$filename" for input: $!}; my @headers = qw/ Sun Mon Tue Wed Thu Fri Sat /; my %headers = map { $headers[$_] => $_ } 0 .. $#headers; my %file_data; while (<$fh>) { next unless my @fields = /(\S[^:]+:)\s+(\w{3})\w*, (\d+)/; my $file = shift @fields; $fields[0] = $headers{ucfirst lc $fields[0]}; push @{ $file_data{$file} }, \@fields; } my $width = max map length, keys %file_data; my $format = "%*s%3s %3s %3s %3s %3s %3s %3s\n"; printf $format, $width, '', @headers; for my $file (sort keys %file_data) { my $days = $file_data{$file}; my @info = ('') x 7; for my $day (@$days) { my ($index, $val) = @$day; $info[$index] = $val; } printf $format, $width, $file, @info; } 

sortie

  Sun Mon Tue Wed Thu Fri Sat Report-20140521.csv: 20 22 22 Report-20140530.csv: 23 23 23 Report-20140606.csv: 24 24 20 Report-20140613.csv: 25 24 21 Report-20140621.csv: 21 21 21 

Vous pouvez utiliser un hash de arrays pour stocker vos données, puis imprimer des valeurs correspondant à vos noms de colonne (c.-à-d. Le jour):

 use warnings; use ssortingct; open my $in, '<', 'in.txt'; my (%data, @record, @day, @n); while (<$in>){ chomp; my @split = split(/\s/); push @record, $split[0]; $split[1] =~ s/,//g; push @day, $split[1]; push @n, $split[2]; } push @{$data{$record[$_]} }, [ $day[$_], $n[$_] ] for 0 .. $#record; my @days = qw(Sun Mon Tues Wed Thu Fri Sat); print "$_ " foreach (@days); print "\n"; for my $report (sort keys %data){ print "$report\t"; for my $val (@{$data{$report}}){ my ($day, $n) = @$val; foreach(@days){ print "$n\t" if $day eq $_; } print "\n"; } } 

Sortie:

 Sun Mon Tues Wed Thu Fri Sat Report-20140521.csv: 20 22 22 Report-20140530.csv: 23 23 23 Report-20140606.csv: 24 24 20 Report-20140613.csv: 25 24 21 Report-20140621.csv: 21 21 21