使用此代码和数据:
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']]
}
所以:
每个块(哈希键)都以“####”分隔
为每个块跳过第3行(例如1003和2222)
每个内部数组的成员用“---”;
对于每个哈希,只存储阻止的第二个成员,以“----”分隔;
这样做的方法是什么?
在此处运行代码:https://eval.in/90200
答案 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"]],
}