2

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

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。我想提取所有 GeneID(所有记录中的第一个字段)、所有细胞带和所有蛋白质序列,并构建一个复杂的数据结构,例如:

$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";
}

任何建设性的反馈将不胜感激。

谢谢!

凯特琳

4

3 回答 3

4

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

这就是正在发生的事情:

  • 如果$/作为输入行分隔符的 是undef,它将把整个文件读取为一行。
  • 因此,@data将只有一个元素包含整个文件。
  • 稍后,当您在循环中对其进行迭代时for,您会在$_.
  • split将为您提供所有字段(尽管第 11 个字段应该具有value_row1_11\nvalue_row2_1.
  • 但是,您还没有看到,因为您的调试只有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;

如果您在某些时候有较大的文件,则逐行读取它对于内存处理也更好。如果你 slurp 整个文件,你需要将它存储在内存中。这样,您一次只需要存储一行来处理数据。


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

于 2013-07-05T06:24:30.777 回答
3

代替

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

你需要这些行:

my @data = <FH>;
chomp @data;
#now you have all lines in the @data array
于 2013-07-05T06:24:14.517 回答
1

这个程序做你想做的。我将 Data::Dumper 的输出重定向到文本文件 o33.txt。

我使用命令行:perl t9.pl Human_716_TSGs.txt > 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;

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

$genes{$gene} = {cytoband => $cytoband,  protein_sequence => $protein_sequence};
于 2013-07-05T15:56:39.513 回答