Perl 使用多记录分隔符将数据解析为数组的数组哈希

Perl 使用多记录分隔符将数据解析为数组的数组哈希,perl,parsing,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

使用此代码和数据:

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
因此:

  • 每个块(散列键)都用“#####”分隔

  • 跳过每个区块的第三行(例如1003和2222)

  • 每个内部数组的成员之间用“---”分隔

  • 对于每个散列,仅存储从blocked开始的第二个成员,以“----”分隔

  • 怎么做


    在此处运行代码:

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

    此代码满足您的需要。它的工作原理是,只要找到一行哈希,就启动一个新的哈希元素。新键被复制到变量
    $key
    中,哈希值被设置为
    [[]]
    。下一个数据行被丢弃

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

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

    我优先使用了
    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
    
    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"]],
    }