Question

J'ai besoin d'aide pour imprimer des données à partir d'un hachage ref / hachage STDOUT ou fichier données dans un ordre spécifique si possible.

J'ai une routine Perl qui utilise des références de hachage comme ceci:

#!/usr/local/bin/perl 

use strict;
use warnings;
use File::Basename;
use Data::Dumper;
my %MyItems;

my $ARGV ="/var/logdir/server1.log";
my $mon = 'Aug';
my $day = '06';
my $year = '2010';

while (my $line = <>)
{
    chomp $line;
    if ($line =~ m/(.* $mon $day) \d{2}:\d{2}:\d{2} $year: ([^:]+):backup:/)
    {
        my $server = basename $ARGV, '.log';
        my $BckupDate="$1 $year";
        my $BckupSet =$2;

        $MyItems{$server}{$BckupSet}->{'MyLogdate'} = $BckupDate;
        $MyItems{$server}{$BckupSet}->{'MyDataset'} = $BckupSet;
        $MyItems{$server}{$BckupSet}->{'MyHost'} = $server;

        if ($line =~ m/(ERROR|backup-size|backup-time|backup-status)[:=](.+)/)
        {
            my $BckupKey=$1;
            my $BckupVal=$2;
            $MyItems{$server}{$BckupSet}->{$BckupKey} = $BckupVal;
        }
    }
}
foreach( values %MyItems ) {
     print "MyHost=>$_->{MyHost};MyLogdate=>$_->{MyLogdate};MyDataset=>$_->{MyDataset};'backup-time'=>$_->{'backup-time'};'backup-status'=>$_->{'backup-status'}\n";
}

sortie en utilisant tombereau:

$VAR1 = 'server1';
$VAR2 = {
          'abc1.mil.mad' => {
                                 'ERROR' => ' If you are sure  is not running, please remove the file and restart ',
                                 'MyLogdate' => 'Fri Aug 06 2010',
                                 'MyHost' => 'server1',
                                 'MyDataset' => 'abc1.mil.mad'
                               },
          'abc2.cfl.mil.mad' => {
                                  'backup-size' => '187.24 GB',
                                  'MyLogdate' => 'Fri Aug 06 2010',
                                  'MyHost' => 'server1',
                                  'backup-status' => 'Backup succeeded',
                                  'backup-time' => '01:54:27',
                                  'MyDataset' => 'abc2.cfl.mil.mad'
                                },

          'abc4.mad_lvm' => {
                                'backup-size' => '422.99 GB',
                                'MyLogdate' => 'Fri Aug 06 2010',
                                'MyHost' => 'server1',
                                'backup-status' => 'Backup succeeded',
                                'backup-time' => '04:48:50',
                                'MyDataset' => 'abc4.mad_lvm'
                              }
        };

Sortie au format que je voudrais voir:

MyHost=>server1;MyLogdate=>Fri Aug 06 2010;MyDataset=>abc2.cfl.mil.mad;backup-time=>Fri Aug 06 2010;backup-status=>Backup succeeded

Juste addded (8/7/2010): fichier journal brut Exemple J'utilise: (a récemment ajouté pour assurer une meilleure représentation du journal source)

Fri Aug 06 00:00:05 2010: abc2.cfl.mil.mad:backup:INFO: backup-set=abc2.cfl.mil.mad
Fri Aug 06 00:00:05 2010: abc2.cfl.mil.mad:backup:INFO: backup-date=20100806000004

Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-size=422.99 GB
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: PHASE END: Calculating backup size & checksums
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-time=04:48:50
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-status=Backup succeeded
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: Backup succeeded
Était-ce utile?

La solution 4

Merci à tous pour leur aide tangue ... Cela fonctionne pour moi.

  for my $Server(keys%MyItems){
    for my $BckupSet(keys%{$MyItems{$Server}}){
      for(sort keys%{$MyItems{$Server}{$BckupSet}}){
        print$_,'=>',$MyItems{$Server}{$BckupSet}{$_},';';
      }
      print"\n";
    }
  }

Autres conseils

J'ai passé quelque temps à regarder votre code et je pense que je l'ai compris.

La raison pour cela était difficile de répondre est que vous avez accidentellement planté un hareng rouge -. Les données dumper sortie

Remarquez comment il montre $VAR1 = 'server1'; puis $VAR2 = { blah };.

Vous avez appelé Dumper comme ceci: print Dumper %MyItems;

Le problème est que Dumper veut une liste de valeurs à décharge, car Perl listes aplanit, structures complexes doivent être passés par référence. Donc, vous devez appeler Dumper comme ceci:

print Dumper \%MyItems;

Cela montre toute la structure.

Quand vous avez appelé dumper plus tôt, vous enlevé par inadvertance une couche de votre structure de données. Les solutions proposées, et votre propre code fonctionnent sur cette structure dépouillée.

Ici, j'ai boulonné sur un code pour gérer la couche supplémentaire d'imbrication (et fait Perl 5.8 compatible):

for my $server_items ( values %MyItems ) {
    for my $record ( values %$server_items ) {

        print join ';', map { 
            # Replace non-existant values with 'undef'
            my $val = exists $record->{$_} ? $record->{$_} : 'undef';

            "'$_'=>$val"  # <-- this is what we print for each field

        } qw( MyHost MyLogdate MyDataset backup-time backup-status );

        print "\n";
    }
}

Il semble que vous avez beaucoup de questions et ont besoin d'aide pour votre tête autour d'un certain nombre de concepts. Je suggère que vous publiez une demande en PerlMonks Demandeurs de Perl Sagesse pour améliorer l'aide de votre code. SO est grande pour la question ciblée, mais PM est plus favorable à réusinage de code.

** réponse originale: **

Pour contourner les problèmes d'analyse que je ne peux pas reproduire, je viens de mettre en %MyItems à la sortie Dumper que vous avez fourni.

Vos avertissements que vous mentionnez ci-dessus ont à voir avec tout ce qui est compliqué et répétitif vous citant le codage avez dans votre déclaration d'impression. Je l'ai remplacé votre déclaration d'impression avec un map pour simplifier le code.

Bordel, une grande carte se joindre blah n'est pas plus simple, vous pourriez penser. Mais vraiment, il est plus simple parce que chaque unité individuelle d'expression est plus petite. Ce qui est plus facile à comprendre et à obtenir le droit? Ce qui est plus facile à modifier et à maintenir dans un manoir correct et cohérent?

print "'foo'=>$_->{foo};'bar'=>$_->{bar};boo'=>$_->{boo};'far'=>$_->{far}\n";

ou

say join ';', map {
    "'$_'=>$item->{$_}"
} qw( foo bar boo far );

Ici, vous pouvez ajouter, supprimer ou de réorganiser votre sortie en changeant simplement la liste des arguments passés à map. Avec l'autre style, vous avez un tas de copier / coller à faire.

La carte ci-dessous, je l'utilise est un peu plus complexe, en ce qu'il vérifie si une clé donnée est définie avant l'impression d'une valeur et d'attribuer une valeur par défaut si aucune est présente.

#!perl

use strict;
use warnings;

use feature 'say';

my %MyItems = (
    'abc1.mil.mad' => {
        'ERROR' => ' If you are sure  is not running, please remove the file and restart ',
        'MyLogdate' => 'Fri Aug 06 2010',
        'MyHost' => 'server1',
        'MyDataset' => 'abc1.mil.mad'
    },

    'abc2.cfl.mil.mad' => {
        'backup-size' => '187.24 GB',
        'MyLogdate' => 'Fri Aug 06 2010',
        'MyHost' => 'server1',
        'backup-status' => 'Backup succeeded',
        'backup-time' => '01:54:27',
        'MyDataset' => 'abc2.cfl.mil.mad'
    },

    'abc3.mil.mad' => {
        'backup-size' => '46.07 GB',
        'MyLogdate' => 'Fri Aug 06 2010',
        'MyHost' => 'server1',
        'backup-status' => 'Backup succeeded',
        'backup-time' => '00:41:06',
        'MyDataset' => 'abc3.mil.mad'
    },

    'abc4.mad_lvm' => {
        'backup-size' => '422.99 GB',
        'MyLogdate' => 'Fri Aug 06 2010',
        'MyHost' => 'server1',
        'backup-status' => 'Backup succeeded',
        'backup-time' => '04:48:50',
        'MyDataset' => 'abc4.mad_lvm'
    }
);


for my $record ( values %MyItems ) {

    say join ';', map { 
        my $val = $record->{$_} // 'undef';  # defined-or requires perl 5.10 or newer.

        "'$_'=>$val"  # <-- this is what we print for each field

    } qw( MyHost MyLogdate MyDataset backup-time backup-status );

}

Non testé, mais il devrait fonctionner en théorie. Cela affichera une ligne de sortie pour chacune des touches pour le principal hachage de MyItems. Si vous le souhaitez sur une seule ligne, vous pouvez simplement laisser tomber le \ n ou ajouter un autre séparateur.

foreach( values %MyItems ) {
     print "MyServer=>$_->{MyServer};MyLogdate=>$_->{MyLogdate};MyDataset=>$_->{MyDataset};backup-time=>$_->{backup-time};backup-status=>$_->{backup-status}\n";
}

Ne pas répondre à la question que vous avez posée, mais cela ne semble pas raisonnable pour moi.

Vous voulez un tableau de hachages pas un hachage de hachages.

hashs ne sont pas commandés, si vous voulez les utiliser alors ordonné un tableau.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top