0

タブ区切りのデータがあります。そのデータをperlで処理したい。私はperlの初心者で、解決方法がわかりませんでした。

これはサンプル テーブルです。元のファイルはほぼ GB です

gi|306963568|gb|GL429799.1|_1316857_1453052 13  1
gi|306963568|gb|GL429799.1|_1316857_1453052 14  1
gi|306963568|gb|GL429799.1|_1316857_1453052 15  1
gi|306963568|gb|GL429799.1|_1316857_1453052 16  1
gi|306963568|gb|GL429799.1|_1316857_1453052 17  1
gi|306963568|gb|GL429799.1|_1316857_1453052 360 1
gi|306963568|gb|GL429799.1|_1316857_1453052 361 1
gi|306963568|gb|GL429799.1|_1316857_1453052 362 1
gi|306963568|gb|GL429799.1|_1316857_1453052 363 1
gi|306963568|gb|GL429799.1|_1316857_1453052 364 1
gi|306963568|gb|GL429799.1|_1316857_1453052 365 1
gi|306963568|gb|GL429799.1|_1316857_1453052 366 1
gi|306963580|gb|GL429787.1|_4276355_4500645 38640   1
gi|306963580|gb|GL429787.1|_4276355_4500645 38641   1
gi|306963580|gb|GL429787.1|_4276355_4500645 38642   1
gi|306963580|gb|GL429787.1|_4276355_4500645 38643   1
gi|306963580|gb|GL429787.1|_4276355_4500645 38644   1
gi|306963580|gb|GL429787.1|_4276355_4500645 38645   1

出力を名前、開始値​​、終了値、平均として取得したい

gi|306963568|gb|GL429799.1|_1316857_1453052 13  17  1   
gi|306963568|gb|GL429799.1|_1316857_1453052 360 366 1   
gi|306963580|gb|GL429787.1|_4276355_4500645 38640   38645   1

誰かが彼らの知恵を共有できれば素晴らしいことです。

4

4 に答える 4

1

一般的なパターンは

use strict;
use warnings;

open my $fh, '<', 'myfile' or die $!;
while (<$fh>) {
  chomp;
  my @fields = split /\t/;
  ...
}

$fields[0]ループ内では、を介してフィールドにアクセスできます$fields[2]


アップデート

私はあなたの質問をよりよく理解しました、そして私はこの解決策があなたのために働くと思います。質問で示したように、入力データがソートされていることを前提としていることに注意してください。

開始値と終了値、合計とカウントをハッシュに蓄積し、で検出され%dataたすべての名前のリストを保持し@namesて、データが読み取られた順序で表示できるようにします。

プログラムは、入力ファイル名をコマンドラインのパラメーターとして想定しています。

平均値は浮動小数点値であるため、平均のフォーマットを考慮する必要があります。現状では、16の有効数字の値が表示されるため、を使用してそれを削減することをお勧めしますsprintf

use strict;
use warnings;

my ($filename) = @ARGV;
open my $fh, '<', $filename or die qq{Unable to open "$filename": $!};

my @names;
my %data;
my $current_name = '';
my $last_index;

while (<$fh>) {
  chomp;
  my ($name, $index, $value) = split /\t/;

  if ( $current_name ne $name or $index > $last_index + 1 ) {
    push @names, $name unless $data{$name};
    push @{ $data{$name} }, {
      start => $index,
      count => 0,
      total => 0,
    };
    $current_name = $name;
  }

  my $entry = $data{$name}[-1];
  $entry->{end} = $index;
  $entry->{count} += 1;
  $entry->{total} += $value;
  $last_index = $index;
}

for my $name (@names) {
  for my $entry (@{ $data{$name} }) {
    my ($start, $end, $total, $count) = @{$entry}{qw/ start end total count /};
    print join("\t", $name, $start, $end, $total / $count), "\n";
  }
}

出力

gi|306963568|gb|GL429799.1|_1316857_1453052 13  17  1
gi|306963568|gb|GL429799.1|_1316857_1453052 360 366 1
gi|306963580|gb|GL429787.1|_4276355_4500645 38640 38645 1
于 2013-02-23T05:42:49.743 に答える
0

これにより、質問のサンプルと同じ出力が生成されます。

#!/usr/bin/env perl -n
#
my ($name, $i, $value) = split(/\t/);

sub print_stats {
    print join("\t", $prev_name, $start, $prev_i, $sum / ($prev_i - $start + 1)), "\n";
}

if ($prev_name eq $name && $i == $prev_i + 1) {
    $sum += $value;
    $prev_i = $i;
}
else {
    if ($prev_name) {
        &print_stats();
    }
    $start = $i;
    $prev_name = $name;
    $sum = $value;
    $prev_i = $i;
}
END {
    &print_stats();
}

次のように使用します。

./parser.pl < sample.txt

更新:コメントの質問への回答:

  • 出力をファイルに出力するには、次のように実行します。./parser.pl < sample.txt > output.txt
  • $prev_name$prev_i初期化されていないため、最初はundef(= NULL)
于 2013-02-23T07:09:04.360 に答える
-1

Text::CSVを使用した例を次に示します。

use Text::CSV;  # This will implicitly use Text::CSV_XS if it's installed

my $parser = Text::CSV->new( { sep_char => '|' } );
open my $fh, '<', 'myfile' or die $!;

while (my $row = $parser->getline($fh)) {
  # $row references an array of field values from the line just read
}

また、マイナーな詳細として、サンプルデータはタブではなくパイプ文字で区切られていますが、これは、質問に答える人のコピー/貼り付けエラーを回避するためかもしれません. 実際のデータがタブ区切りの場合、 の代わりに に設定sep_charします。"\t"'|'

于 2013-02-23T10:06:52.550 に答える
-1

あなたはこのようなことをすることができます....

open (FILE, 'data.txt');
while (<FILE>) {
chomp;
($name, $start_value, $end_value, $average) = split("\t");
print "Name: $name\n";
print "Start Value: $start_value\n";
print "End Value: $End_Value\n";
print "Average: %average
print "---------\n";
}
close (FILE);
exit;

それらはGenBankファイルのように見えます...だから、開始値、終了値、平均をどこで取得しているのかわかりません。

于 2013-02-23T05:21:14.433 に答える