我想要一个哈希结构,每行以&gt; 开头是关键,而直到下一个&gt; 的行是该键的值:< / p>
while (<DATA>) {
$line1 = $_;
chomp($line1);
if ($line1 =~ /^>/) {
while (<DATA>) {
last if $line1 =~ /^>/;
$value .= $_;
}
$hash{$line1} = $value;
}
}
foreach my $key(%hash) {
print "$key :$hash{$key}\n";
}
__DATA__
>label1
line1\n
line2\n
>label2
line1\n
line2\n
答案 0 :(得分:5)
我认为使用具有外部范围的关键变量是最简单的方法:
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
my $key = 'unlabeled';
my %value;
while (defined(my $line = <DATA>)) {
chomp $line;
# key line
if ($line =~ /^>(.*)/) {
$key = $1;
next;
}
# value line
push @{$value{$key}}, $line;
}
say "$_: " . join ', ' => @{$value{$_}} for keys %value;
__DATA__
>label1
line1
line2
>label2
line1
line2
label1: line1, line2
label2: line1, line2
我们将最后看到的哈希键保存在行迭代循环外的变量$key
中。当循环看到下一个关键行时,它将替换$key
字符串。如果不存在新密钥的数组,perl的autovivification机制会在散列内创建一个新的空数组。如果$key
下的哈希中已存在某些内容,则会在现有行之后添加新行。
修改:如果您的输入不是以键行开头,则第一个非键行将添加到键unlabeled
。
编辑2 :如果您想要连接标签的行,可以通过join "\n" => @{$value{$_}}
轻松完成。如果你想要那样只有 你可以扔掉数组的东西并使用@perreal的解决方案,它非常相似,但只是连接新行。
编辑3 :是的,autovivification! :)(谢谢@TLP)
答案 1 :(得分:1)
use warnings;
use strict;
my %hash;
my $key;
foreach (<DATA>) {
chomp;
if (/^>(.*)$/) { $key = $1; }
else { $hash{$key} .= $_}
}
foreach $key(keys %hash) {
print "$key :$hash{$key}\n";
}
__DATA__
>label1
line1\n
line2\n
>label2
line1\n
line2\n