我有data.txt,数据如下所示。我有大约一百个名称,包含3个常数ID 100,200,300,每个名称有32个数据值。
NAME: xyz
ID: 100
DATA: 10 15 99 13 ...
ID: 200
DATA: 23 45 78 90..
ID: 300
DATA: 45 67 89 56
NAME: abc
ID: 100
DATA: 2 4 787 8..
ID: 200
DATA: 12 14 17..
ID: 300
DATA: 45 34 22..
我需要将此数据写入另一个看起来像
的文件xyz_100, xyz_200,xyz_300,abc_100,...
10 , 23 , 45 ,2
15 , 45 ,67 ,4
我构建一个哈希来存储值,但是现在我的代码会覆盖前两个条目并存储最后一个条目。如何保存前两个条目,如果我可以简化代码,请告诉我。
#!/usr/local/bin/perl
use diagnostics;
use strict;
use warnings;
my @avar_names;
my %record;
local $/ = '';
open my $fh, '<', 'datalog.dat' or die "failed: $!";
while (<$fh>) {
chomp;
my %avar;
while (/^([A-Z:]+):\s*(.*)/mg) {
$avar{$1} = $2;
}
my $avar_name = "$avar{NAME}_$avar{ID}";
push @avar_names, $avar_name;
$record{$avar_name} = $avar{DATA};
use Data::Dumper;
print Dumper \%record;
}
答案 0 :(得分:2)
存在一致性问题:local
行使第一个,而整个处理整个NAME / ID数据(然后,由于while(//mg)
循环) ,但代码正在进行逐行处理。
我建议简单:逐个处理文件行,对于每一个,通过当前行上的正则表达式识别“NAME / ID”对(ID可以是DATA)。
为了实现这一目标,%avar
需要 才能成为while
<$fh>
的本地人,因为它必须跟踪最后一个它从文件的最后几行得到的NAME / ID引用。
未使用@avar_names
数组。
最后,你想在最后打印结果记录(我猜),但这是你的选择。
这是我试图改变上述内容的程序:
#!/usr/local/bin/perl
use diagnostics;
use strict;
use warnings;
my @avar_names;
my %record;
#local $/ = ''; ## commented out
open my $fh, '<', 'datalog.dat' or die "failed: $!";
my %avar; ## moved here
while (<$fh>) {
chomp;
if (m/^([A-Z]+):\s*(.*)/) { ## if, not a while
$avar{$1} = $2;
## ensure we have at least our 3 keys, process only if we met DATA
if (exists($avar{NAME}) && exists($avar{ID}) && exists($avar{DATA}) && $1 eq 'DATA') {
my $avar_name = "$avar{NAME}_$avar{ID}";
push @avar_names, $avar_name; ## not used
$record{$avar_name} = $avar{DATA};
}
}
}
use Data::Dumper;
print Dumper \%record;
输出:
$VAR1 = {
'xyz_100' => '10 15 99 13 ...',
'xyz_300' => '45 67 89 56',
'abc_200' => '12 14 17..',
'abc_300' => '45 34 22..',
'abc_100' => '2 4 787 8..',
'xyz_200' => '23 45 78 90..'
};
答案 1 :(得分:1)
你需要这样的东西:
my @avars;
# ... some code
while (<$fh>) {
# more code
my %curr;
while (/^([A-Z:]+):\s*(.*)/mg) {
$curr->{$1} = $2;
}
if (%curr) {
push @avars, \%curr;
my $avar_name = "$curr{NAME}_$curr{ID}";
push @avar_names, $avar_name;
$record{$avar_name} = $avar{DATA};
}
# ....