2009-05-07 6 views
1

Le code suivant génère une liste du nombre moyen de clients connectés par sous-réseau. Actuellement, je dois le faire passer par tri | uniq | grep -v HASH.Comment accéder à mes tableaux anonymes?

Essayer de garder tout en perl cela ne fonctionne pas:

foreach $subnet (keys %{keys %{keys %days}}) { 
    print "$subnet\n"; 
} 

Source est la suivante:

foreach $file (@ARGV) { 
     open(FH, $file) or warn("Can't open file $file\n"); 
     if ($file =~ /(2009\d{4})/) { 
      $dt = $+; 
     } 
     %hash = {}; 
     while(<FH>) { 
      @fields = split(/~/); 
      $subnet = $fields[0]; 
      $client = $fields[2]; 
      $hash{$subnet}{$client}++; 
     } 
     close(FH); 
     $file = "$dt.csv"; 
     open(FH, ">$file") or die("Can't open $file for output"); 
     foreach $subnet (sort keys %hash) { 
       $tot = keys(%{$hash{$subnet}}); 
       $days{$dt}{$subnet} = $tot; 
       print FH "$subnet,$tot\n"; 
       push @{$subnet}, $tot; 
     } 
     close(FH); 
    } 

    foreach $day (sort keys %days) { 
     foreach $subnet (sort keys %{$days{$day}}) { 
      $tot = $i = 0 ; 
      foreach $amt (@{$subnet}) { 
       $i++; 
       $tot += $amt; 
      } 
      print "$subnet," . int($tot/$i) . "\n"; 
     } 
    } 

Comment puis-je éliminer la nécessité pour le tri | processus uniq en dehors de Perl? Le dernier foreach m'obtient les id de sous-réseau qui sont les noms «anonymes» pour les tableaux. Il génère ces plusieurs fois (un pour chaque jour où ce sous-réseau a été utilisé).

+0

Etes-vous en train d'essayer de les imprimer? Jetez un oeil à Data :: Dumper. –

+0

Quelle partie de votre code fonctionne, quelle partie ne fonctionne pas? Qu'essayez-vous d'accomplir? – innaM

+1

Je ne suis pas sûr de la question, mais le code de débogage serait plus facile avec des restrictions: use strict, use warnings (strict voudra que tu déclares tes variables avec 'my') – Anonymous

Répondre

2

mais cela semblait plus facile que de combiner feuilles de calcul en Excel.

En fait, les modules comme Spreadsheet::ParseExcel rendent cela très facile, dans la plupart des cas. Vous devez toujours gérer les lignes comme si vous utilisiez le format CSV ou l'adressage de type "A1", mais vous n'avez pas à effectuer l'étape d'exportation. Et puis vous pouvez sortir avec Spreadsheet::WriteExcel!

J'ai utilisé ces modules pour lire une feuille de calcul de quelques centaines de chèques, trier et arranger et tondre le contenu, et écrire à un nouveau pour la livraison à un comptable.


Dans cette partie:

foreach $subnet (sort keys %hash) { 
     $tot = keys(%{$hash{$subnet}}); 
     $days{$dt}{$subnet} = $tot; 
     print FH "$subnet,$tot\n"; 
     push @{$subnet}, $tot; 
} 

sous-réseau $ est une chaîne, mais vous l'utilisez dans la dernière déclaration comme une référence de tableau. Comme vous n'avez pas strictures, il le traite comme une référence logicielle à une variable dont le nom est identique au contenu de $ subnet. Ce qui est correct si vous le voulez vraiment, mais c'est déroutant. Quant à clarifier la dernière partie ...

Mise à jour Je suppose que c'est ce que vous cherchez, où la valeur du sous-réseau n'est sauvegardée que si elle n'est pas apparue avant, même d'un autre jour (?):

use List::Util qw(sum); # List::Util was first released with perl 5.007003 (5.7.3, I think) 
my %buckets; 
foreach my $day (sort keys %days) { 
    foreach my $subnet (sort keys %{$days{$day}}) { 
     next if exists $buckets{$subnet}; # only gives you this value once, regardless of what day it came in 
     my $total = sum @{$subnet}; # no need to reuse a variable 
     $buckets{$subnet} = int($total/@{$subnet}; # array in scalar context is number of elements 
    } 
} 

use Data::Dumper qw(Dumper); 
print Dumper \%buckets; 
+0

Voyant que je génère les fichiers CSV, j'ai pensé qu'il serait plus facile d'éliminer une étape supplémentaire. Merci pour les liens. –

+0

@Anonyme, c'est plus propre, mais ça me donne quand même 1667 enregistrements qui, après avoir traversé sort et uniq, descendent à 196. Ce que je voudrais, c'est un moyen d'accéder aux valeurs du sous-réseau une fois ... –

+0

@Anonymous, c'est beaucoup mieux, mais me donne toujours les types de réponses HASH (0xab5954). Je pense que la meilleure chose à faire serait d'éliminer les tableaux anonymes en quelque sorte. –

0

appuyant sur @ suggestions de Anonymous, j'ai construit un hachage des noms de sous-réseau pour acess les tableaux:

..

  push @{$subnet}, $tot; 
      $subnets{$subnet}++; 
    } 
    close(FH); 
} 

use List::Util qw(sum); # List::Util was first released with perl 5.007003 

foreach my $subnet (sort keys %subnets) { 
    my $total = sum @{$subnet}; # no need to reuse a variable 
    print "$subnet," . int($total/@{$subnet}) . "\n"; # array in scalar context is number of elements 
} 

Je ne sais pas si c'est la meilleure solution, mais je n'ai plus les doublons.

Questions connexes