【问题标题】:populating a multi - level hash填充多级散列
【发布时间】:2011-09-26 12:32:08
【问题描述】:

我有这个数据集 - 我只关心类 id,process@server: 我正在尝试将所有三个加载到多级哈希中。

class_id: 995   (OCAive   )  ack_type: NOACK     supercede:  NO  copy:  NO  bdcst:  NO
PID                                    SENDS   RECEIVES   RETRANSMITS   TIMEOUTS MEAN    S.D.    #
21881  (rocksrvr@ith111          )          1          1             0          0
24519  (miclogUS@ith110          )          1          1             0          0
26163  (gkoopsrvr@itb101          )          1          1             0          0
28069  (sitetic@ith100           )         23          4             0          0
28144  (srtic@ithb10           )         33          5             0          0
29931  (loick@ithbsv115      )          1          1             0          0
87331  (rrrrv_us@ith102          )          1          1             0          0
                                  ---------- ----------    ---------- ---------- ------- ------- ------ 
                                          61         14             0          0

当我尝试填充哈希时,它并没有得到太多(数据转储器结果如下)

$VAR1 = '';
$VAR2 = {
    '' => undef
};

这是代码:

#!/usr/bin/perl -w
use strict;
my $newcomm_dir = "/home/casper-compaq/work_perl/newcomm";
my $newcomm_file = "newcomm_stat_result.txt";

open NEWCOMM , "$new_comm_dir$newcomm_file";
while (<NEWCOMM>) {
    if ($_ =~ /\s+class_id:\s\d+\s+((\w+)\s+)/){
        my $message_class = $1;
    }
    if ($_ =~ /((\w+)\@\w+\s+)/) {
        my $process = $1;
    }
    if ($_ =~ /(\w+\@(\w+)\s+)/) {
        my $servers = $1;
    }

    my $newcomm_stat_hash{$message_class}{$servers}=$process;


    use Data::Dumper;
    print Dumper (%newcomm_stat_hash);
}

【问题讨论】:

    标签: regex perl hash


    【解决方案1】:

    您在 if 中的 my 声明只有在 if 块结束之前的范围,并且您的哈希分配不应该有 my.尝试在 while 循环之前声明 %newcomm_stat_hash,并在 while 块的顶部声明 $message_class$process$servers

    您可能还想检查您的打开是否失败;我怀疑你错过了 / 那里。

    【讨论】:

      【解决方案2】:

      除了声明问题之外,您的正则表达式还存在多个问题。我建议在尝试将每个变量插入散列之前,确保将预期的输出放入每个变量中。

      一方面,您需要将括号匹配为\(\),否则它们只会被解释为变量容器。

      【讨论】:

      • 在目录末尾添加一个斜线并在顶部进行声明 - 谢谢。
      【解决方案3】:

      您的文件是否正在打开?

      我认为你需要改变:

      open NEWCOMM , "$new_comm_dir$newcomm_file";
      

      收件人:

      open NEWCOMM , $new_comm_dir.'/'.$newcomm_file;
      

      【讨论】:

      • 是的 - 我应该并且从现在开始将“或死$!”读入文件后。太尴尬了。
      【解决方案4】:

      我怀疑您的主要错误是您的文件未打开,因为路径在目录和文件名之间缺少/。您可以使用 autodie pragma 来检查打开是否成功,也可以使用or die "Can't open file: $!"

      您有一些范围问题。首先,$message_class 将在整个循环中未定义,因为它的范围仅在一次迭代内持续。如果您希望以后能够使用它,您可能还希望将散列放在循环之外。

      我在标题行检查中添加了next 语句,因为其他检查在该特定行中将无效。如果你想更精确,你可以把整个事情放在循环之外,只做一个单行检查。

      进程和服务器这两个变量不需要,直接使用即可,同时使用。

      最后,您可能希望将哈希的引用发送到打印中的Data::Dumper,否则哈希会扩大,打印会有些误导。

      #!/usr/bin/perl -w
      use strict;
      use autodie;
      my $newcomm_dir = "/home/casper-compaq/work_perl/newcomm/"; 
      my $newcomm_file = "newcomm_stat_result.txt";
      
      open my $fh, '<', "$new_comm_dir$newcomm_file";
      
      my $message_class;
      my %newcomm_stat_hash;
      while (<$fh>) {
          if (/^\s+class_id:\s+\d+\s+\((\w+)\)\s+/){
              $message_class = $1;
              next;
          }
          if (/(\w+)\@(\w+)/) {
              $newcomm_stat_hash{$message_class}{$2}=$1;
          }
      }
      use Data::Dumper;
      print Dumper \%newcomm_stat_hash;
      

      【讨论】:

      • 文件未打开 - 变量超出范围 - 将它们限定在脚本的根目录(开头)填充散列。哈希的更深节点的合并,我真的很喜欢。以前从未见过它,它使散列更具可读性。 $newcomm_stat_hash{$message_class}{$2}=$1
      • @capser 您应该用绿色复选标记标记答案,以表示最佳答案。
      • 所有的 cmets 都有帮助,但减少一些语句会使代码更具可读性。 $newcomm_stat_hash{$message_class}{$2}=$1;
      猜你喜欢
      • 1970-01-01
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-04
      • 1970-01-01
      • 2020-10-17
      • 1970-01-01
      相关资源
      最近更新 更多