【问题标题】:perl - help with hash and dumping of recordsperl - 帮助哈希和转储记录
【发布时间】:2011-04-01 21:35:29
【问题描述】:

我有一个 perl 脚本,它只保留命名集的最后一组记录,而且我有不止一组记录。所以它在哈希中写入数据并只保留最后一组。我需要帮助打印所有记录。 谢谢!

这是我的脚本的副本:

#!/usr/local/bin/perl 

use strict;
use warnings;
use Data::Dumper;

my ($ServerName)=@ARGV;
my %MyItems;
foreach my $ServerName(@ARGV){
   while (my $line = <>){
     chomp $line;
              if ($line =~ m/.* \w+ \d{2} (\d{2}:\d{2}:\d{2}) \d{4}: ([^:]+):backup:/){
                  my $ServerName = basename $ARGV, '.mydomain.com.backup-software.log'; #$ARGV is reading input from command line
                  my $BckupSet =$2;
                  my $BckupVal=$1;
                  $MyItems{$ServerName}{$BckupSet}->{'1-Server'}    = $ServerName;
                  $MyItems{$ServerName}{$BckupSet}->{'2-BackupSet'} = $BckupSet;
                  $MyItems{$ServerName}{$BckupSet}->{'3-StartTime'} = $BckupVal;

                  if ($line =~ m/(backup-date)[:=](.+)/){
                      my $BckupKey="4-DateStamp";
                      my $BckupVal=$2;
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                  }

                  if ($line =~ m/(backup-time)[:=](.+)/){
                      my $BckupKey="5-Duration";
                      my $BckupVal=$2;
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                  }
                  if ($line =~ m/(backup-size)[:=](.+)/){
                      my $BckupKey="6-Size";
                      my $BckupVal=$2;
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                  }
                  if ($line =~ m/(Backup succeeded)/){
                      my $BckupKey="7-Status";
                      my $BckupVal="Succeeded";
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                  }
                  if ($line =~ m/(ERROR)[:=](.+)/){
                      my $BckupKey="8-Status";
                      my $BckupVal="Unsuccessful";
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                      print "$BckupKey=$BckupVal\n" if debug;
                  }
              }
   } #endwhile
   print Dumper(\%MyItems);
   for my $ServerName(keys%MyItems){
     for my $BckupSet(keys%{$MyItems{$ServerName}}){
       for(sort keys%{$MyItems{$ServerName}{$BckupSet}}){
         #print$_,'=>',$MyItems{$ServerName}{$BckupSet}{$_},';';
         print$_,'=',$MyItems{$ServerName}{$BckupSet}{$_},';';
       }
       print"\n";
     }
   }
} #END foreach

这是它转储时的样子:

$VAR1 = {
          'server1.name.colo' => { 
                                        'set1' => {
                                                               '3-StartTime' => '07:08:15',
                                                               '1-Server' => 'server1.name.colo',
                                                               '6-Size' => '72.04 GB',
                                                               '7-Status' => 'Succeeded',
                                                               '4-DateStamp' => '20100820060002',
                                                               '5-Duration' => '01:08:13',
                                                               '2-BackupSet' => 'set1',
                                                               '8-Status' => 'Unsuccessful'
                                                             },
                                        'set2' => {
                                                                '7-Status' => 'Succeeded',
                                                                '6-Size' => '187.24 GB',
                                                                '3-StartTime' => '01:51:25',
                                                                '4-DateStamp' => '20100820000003',
                                                                '1-Server' => 'server1.name.colo',
                                                                '5-Duration' => '01:51:21',
                                                                '2-BackupSet' => 'set2'
                                                              },
                                        'set3' => {
                                                              '3-StartTime' => '23:00:05',
                                                              '4-DateStamp' => '20100814230003',
                                                              '1-Server' => 'server1.name.colo',
                                                              '8-Status' => 'Unsuccessful',
                                                              '2-BackupSet' => 'set3'
                                                            },
                                        'set4' => {
                                                              '7-Status' => 'Succeeded',
                                                              '6-Size' => '427.75 GB',
                                                              '3-StartTime' => '00:43:20',
                                                              '4-DateStamp' => '20100819200004',
                                                              '1-Server' => 'server1.name.colo',
                                                              '5-Duration' => '04:43:14',
                                                              '2-BackupSet' => 'set4'
                                                            },
                                        'set3' => {
                                                              '7-Status' => 'Succeeded',
                                                              '6-Size' => '46.42 GB',
                                                              '3-StartTime' => '04:42:59',
                                                              '4-DateStamp' => '20100820040002',
                                                              '1-Server' => 'server1.name.colo',
                                                              '5-Duration' => '00:42:56',
                                                              '2-BackupSet' => 'set3'
                                                            }
                                      }
        };

【问题讨论】:

  • 您希望看到什么?超过 1 个服务器?

标签: perl multidimensional-array hash hash-of-hashes


【解决方案1】:

根据调试输出,您的问题似乎在这里:

if ($line =~ m/(ERROR)[:=](.+)/){
    my $BckupKey="8-Status";
    my $BckupVal="Unsuccessful";
    $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
    print "$BckupKey=$BckupVal\n" if debug;
}

要保存所有错误,您需要将该哈希槽视为对数组的引用:

if ($line =~ m/(ERROR)[:=](.+)/){
    my $BckupKey="8-Status";
    my $BckupVal="Unsuccessful";
    push @{ $MyItems{$ServerName}{$BckupSet}{$BckupKey} } => $BckupVal;
    print "$BckupKey=$BckupVal\n" if debug;
}

在您的转储中,8-Status 值将类似于

'8-Status' => ['Unsuccessful', 'Other error', 'Et cetera'],

如果你想稍后循环它们,你会做类似的事情

foreach my $err (@{ $MyItems{$ServerName}{$BckupSet}{$BckupKey} }) {
    print "got $err\n";
}

要获得第一个,你会写

print $MyItems{$ServerName}{$BckupSet}{$BckupKey}[0], "\n";

另一个问题是

foreach my $ServerName(@ARGV){
   while (my $line = <>){

意识到while (&lt;&gt;) { ... } 隐式循环遍历所有以@ARGV 命名的文件,因此将其嵌套在@ARGV 上的循环中并不十分有意义。如果您的命令行格式为

$ readlogs server1 server2 server3 log1 log2

那么您首先要从@ARGV 中删除使用shift 的服务器。区分用户想要作为服务器主机名的参数可能很棘手。一种约定是使用-- 表示选项处理结束,因此您可以

my @servers;
while (@ARGV) {
  my $server = shift;
  last if $server eq "--"
  push @servers => $server;
}

die "Usage: $0 server .. -- log ..\n" unless @ARGV;

while (<>) {
  # ...
}

【讨论】:

  • 谢谢。如果条件也一样,我会将推送应用于我的所有其他人吗?也打印密钥?
  • @jda6one9 对所有这些都使用push 会起作用,但您可能会对单元素数组感到恼火。这样做的好处是永远不会丢弃数据,但它可能对你想做的事情过于宽容。
  • 你之前帮助我使用了这个 --> xargs -I{} ./myscript.pl {}
【解决方案2】:

这是题外话,但任何时候您需要深度嵌套的数据结构,您的代码都会面临变得臃肿且难以阅读的风险。简单的便利变量在简化事情和减轻代码读者(从现在起 3 个月后)不得不执行许多心理差异方面大有帮助:

# A convenience var.
my $bs = $MyItems{$ServerName}{$BckupSet};

# The rest of your code can use the var.
$bs->{'1-Server'} = $ServerName;

此外,您还有几个 if 块,它们的功能基本相同。似乎适合某种调度表策略:

my @dispatch_table = (
    {
        regex => qr/(backup-date)[:=](.+)/,
        key   => '4-DateStamp',
        val   => sub { $2 },
    },
    {
        # etc.
    },
);

然后你的if 块归结为这样的东西:

for my $dt (@dispatch_table){
    next unless $line =~ $dt->{regex};
    $bs->{ $dt->{key} } = $dt->{val}->();
}

【讨论】:

  • @FM - 感谢您的提示!在过去的几周里,我基本上已经学会了 perl。所以,我会尽我所能去学习。
猜你喜欢
  • 2011-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多