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は、既存の行の後に新しい行が追加されます。

編集: 入力がキー行で始まらない場合、最初の非キー行がキーに追加されます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 に答える