3

我想要一个哈希结构,以>开头的每一行都是键,直到下一个 > 的行是该键值:

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
4

2 回答 2

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 的自动激活机制会在散列中创建一个新的空数组。如果 下的散列中已经存在某些内容,$key则会在现有行之后添加新行。

编辑:如果您的输入不是以关键行开头,则第一个非关键行将添加到 key unlabeled

编辑 2:如果您想要连接标签的行,这可以通过join "\n" => @{$value{$_}}. 如果你想要这样,只有你可以扔掉数组的东西并使用@perreal 的解决方案,它非常相似,但只是连接新行。

编辑3:是的,自动复活!:) (感谢@TLP)

于 2012-09-20T11:42:08.720 回答
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
于 2012-09-20T11:50:53.240 回答