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

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)

mem*_*owe 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
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)