迭代地在Perl中的匹配行之后抓取多行?

时间:2012-09-20 11:28:38

标签: perl hash pattern-matching

我想要一个哈希结构,每行以&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

2 个答案:

答案 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