处理制表符分隔文件并将字段存储在复杂数据结构中

时间:2013-07-05 06:05:36

标签: perl

我正在尝试处理以下文件:

http://bioinfo.mc.vanderbilt.edu/TSGene/Human_716_TSGs.txt

...由700多条记录组成,每条记录有11个制表符分隔字段。每个记录由相同的重复类别组成,即GeneID,Gene_symbol,Alias,Xref,Chromosome,Cytoband,Full_name,Gene_type,Description,Nucleotide_Sequence和Protein_Sequence。我想提取所有的GeneIDs(所有记录中的第一个字段),所有的cytobands,以及所有的蛋白质序列,并构建一个复杂的数据结构,例如:

$genes->{$gene_name}{$cytoband} = $protein_sequence;

我的问题是我只能抓住第一条记录(11个字段)并将它们分配到列表中。我不知道如何捕获和存储构成一列的所有字段。我最初的尝试如下:

use strict;
use warnings;
use autodie;

my ($gene, $symbol, $alias, $xref,
    $chromo, $cytoband, $full_name, $gene_type, $desc, $nuc_seq, $pro_seq);

open FH, '<', 'human_tsgs.txt';
    my @data = do {local $/; <FH>};
close FH;

for (@data)
{
    ($gene, $symbol, $alias, $xref, $chromo, $cytoband,
     $full_name, $gene_type, $desc, $nuc_seq, $pro_seq) = split "\t", $_;

     #print $gene, "\n";
}

任何有建设性的反馈都会受到赞赏。

谢谢!

凯特琳

3 个答案:

答案 0 :(得分:4)

问题在于您阅读文件的方式。您可以通过在块中$/取消local来取消定义$/

以下是发生的事情:

  • 如果undef the input line seperator@data,则会将整个文件读为一行。
  • 因此,for只有一个包含整个文件的元素。
  • 稍后,当您在$_循环中迭代它时,您将获得split中的整个文件。
  • value_row1_11\nvalue_row2_1将为您提供所有字段(尽管第11个字段应为print $gene
  • 你还没有看到,因为你的调试只有$/,这是第一个值。

您需要做的是逐行读取文件。没有必要干涉open my $fh, '<', 'human_tsgs.txt' or die $!; while ( my $line = <$fh> ) { chomp $line; my ( $gene, $symbol, $alias, $xref, $chromo, $cytoband, $full_name, $gene_type, $desc, $nuc_seq, $pro_seq ) = split "\t", $line; } close $fh;

{{1}}

如果您在某些时候有更大的文件,逐行读取它也更适合内存处理。如果您啜饮整个文件,则需要将其存储在内存中。这样,您只需要一次存储一行来处理数据。


实现此目的的另一种方法是使用Text::CSV模块。

答案 1 :(得分:3)

而不是

my @data = do {local $/; <FH>};

你需要这些:

my @data = <FH>;
chomp @data;
#now you have all lines in the @data array

答案 2 :(得分:1)

这个程序可以满足您的需求。我将Data :: Dumper的输出重定向到文本文件o33.txt。

我使用了命令行: perl t9.pl Human_716_TSGs.txt&gt; o33.txt

(t9.pl是以下程序)

#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV_XS;
use autodie;

my $csv = Text::CSV_XS->new ( { binary => 1, eol => "\n", sep_char => "\t" } );

my %genes;
while (my $row = $csv->getline (*ARGV)) {
    my ($gene, $cytoband, $protein_sequence) = @$row[0, 5, 10];
    next unless $gene =~ /^\d+$/; # eliminate header and final line
    $genes{$gene}{$cytoband} = $protein_sequence;
}

use Data::Dumper; print Dumper \%genes;

更新:看看genid(第一个字段)是如何唯一的(并且您确定它们将是唯一的),您可能需要不同的结构,如:

$genes{$gene} = {cytoband => $cytoband,  protein_sequence => $protein_sequence};