sha*_*haq 3 perl hash pattern-matching
我想要一个哈希结构,每个以>开头的行是键,而直到下一个>的行是该键的值:
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
Run Code Online (Sandbox Code Playgroud)
我认为使用具有外部范围的关键变量是最简单的方法:
#!/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
Run Code Online (Sandbox Code Playgroud)
label1: line1, line2
label2: line1, line2
Run Code Online (Sandbox Code Playgroud)
我们将最后看到的哈希键保存$key在行迭代循环外的变量范围内.当循环看到下一个关键行时,它将替换该$key字符串.如果不存在新密钥的数组,perl的自动修复机制会在哈希内部创建一个新的空数组.如果哈希中已存在某些内容,$key则会在现有行之后添加新行.
编辑:如果您的输入不是以键行开头,则第一个非键行将添加到键中unlabeled.
编辑2:如果你想要连接标签的行,这可以很容易地完成join "\n" => @{$value{$_}}.如果你想要这样只有你可以抛出数组的东西并使用@perreal的解决方案非常相似,但只是连接新的行.
编辑3:是的,autovivification!:)(谢谢@TLP)