使用多个记录分隔符将数据解析为数组数组的散列

时间:2014-01-16 03:42:25

标签: perl parsing

使用此代码和数据:

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

my %hash;
local $/ = '###############';

while (<DATA>) {
   chomp;
   my @items = split "\n"  or next;
   chomp(@items);
   print Dumper \@items;
}


__DATA__
###############
0 FOO 
entry 1003
entry 1001
entry 9999
---------------
entry 3333
entry 7777
###############
1 BAR 
entry 2222
entry 2001

我希望创建以下数据结构:

   $VAR = {
             '0 FOO'  => [['entry 1001','entry 9999'],['entry 7777']],
             '1 BAR'  =>  [['entry 2001']]
           }

所以:

  1. 每个块(哈希键)都以“####”分隔

  2. 为每个块跳过第3行(例如1003和2222)

  3. 每个内部数组的成员用“---”;

  4. 分隔
  5. 对于每个哈希,只存储阻止的第二个成员,以“----”分隔;

  6. 这样做的方法是什么?

    在此处运行代码:https://eval.in/90200

1 个答案:

答案 0 :(得分:2)

我发现将整个数据块一次读入内存很少有帮助,因为您只需将它们拆分并删除换行符等。通常更容易维护一些简单的状态数据并逐行处理文件。 / p>

此代码可满足您的需求。它的工作原理是每当找到一行哈希值时启动一个新的哈希元素。新密钥将复制到变量$key中,哈希值将设置为[ [ ] ]。下一条数据线将被丢弃。

类似地,一行连字符会在当前哈希值的末尾添加另一个空数组,并丢弃下一个数据行。

任何其他行只会添加到当前哈希值的最后一个数组中。

我使用Data::Dump优先于Data::Dumper,因为我发现它产生了更可读的输出。但是,它不是核心模块,如果您希望效仿,可能需要安装它。

use strict;
use warnings;

use Data::Dump;

my %data;
my $key;
while (<DATA>) {

  chomp;

  if (/^#+$/) {
    chomp ($key = <DATA>);
    $data{$key} = [ [ ] ];
    <DATA>;
  }
  elsif (/^-+$/) {
    push @{ $data{$key} }, [ ];
    <DATA>;
  }
  else {
    push @{ $data{$key}[-1] }, $_;
  }
}

dd \%data;


__DATA__
###############
0 FOO 
entry 1003
entry 1001
entry 9999
---------------
entry 3333
entry 7777
###############
1 BAR 
entry 2222
entry 2001

<强>输出

{
  "0 FOO " => [["entry 1001", "entry 9999"], ["entry 7777"]],
  "1 BAR " => [["entry 2001"]],
}