有选择地将数组的元素连接到新数组的较少元素中

时间:2012-05-10 22:07:39

标签: perl sequence bioinformatics fasta bioperl

我在操作一系列.fasta格式的DNA序列数据时遇到了一些麻烦。我特别想做的是将一个包含几千个序列的文件和文件中每个序列的序列数据连接到文件中的一行。 [Fasta格式如下:序列ID以>开头。之后,该行上的所有内容都是描述。在下一行中,存在与该ID对应的序列。这可以无限期地继续,直到下一行以>开头,这是文件中下一个序列的id]因此,在我的特定文件中,我的大多数序列都在多行上,所以我想做的是基本上删除换行符,但只删除序列数据之间的新行,而不是序列数据和序列ID行之间的新行(以>开头)。

我这样做是因为我希望能够获得每个序列的序列长度(通过长度,我相信这是最简单的方法),然后获得整个文件中所有序列的平均序列长度。 / p>

到目前为止,这是我的脚本,似乎不想工作:

#!/usr/bin/perl -w


##Subroutine
sub get_file_data1 { 
    my($filename) = $_[0];
    my @filedata = ();
    unless( open(GET_FILE_DATA, $filename)) {
    print STDERR "Cannot open file \"$filename\"\n\n";
    exit;
    }
    @filedata = <GET_FILE_DATA>;
    close GET_FILE_DATA;
    return @filedata;
}



##Opening files
my $fsafile = $ARGV[0];
my @filedata = &get_file_data1($fsafile);


##Procedure
my @count;
my @ids;
my $seq;

foreach $seq (@filedata){
        if ($seq =~ /^>/) {push @ids, $seq;
                                 push @count, "\n";
    }
        else {push @count, $seq;
    }
}


foreach my $line (@count) {
    if ($line =~ /^[AGTCagtc]/){
         $line =~ s/^([AGTCagtc]*)\n/$1/;
    }
}

##Make a text file to have a look
open FILE3, "> unbrokenseq.txt" or die "Cannot open output.txt: $!";

foreach (@count)
{
    print FILE3 "$_\n"; # Print each entry in our array to the file
}
close FILE3;


__END__
##Creating array of lengths
my $number;
my @numberarray;
foreach $number (@count) {
                push @numberarray, length($number);
                }
print @numberarray;


__END__
use List::Util qw(sum);

sub mean {
    return sum(@numberarray)/@numberarray;
}

“程序”部分的第二个 foreach 行出了问题,我似乎无法弄清楚它是什么。请注意END行之后的代码我还没有尝试过,因为我似乎无法在过程步骤中获取代码来执行我想要的操作。知道我怎么能得到一个包含完整序列元素的漂亮数组(我选择从新数组中删除序列ID行)?当我可以获得一系列长度,然后我可以平均?

最后,我不幸地承认我无法让Bio :: Perl在我的电脑上工作,我已经尝试了几个小时,但错误超出了我的修复技能。我会和那些希望帮助我解决Bio :: perl问题的人交谈。但是现在我只能在没有它的情况下继续努力。

谢谢!对不起这篇文章的篇幅,我感谢你的帮助。

安德鲁

3 个答案:

答案 0 :(得分:0)

您的第二个循环的问题在于您实际上并未更改@count中的任何内容,因为$line包含@count中值的副本。

但是,如果您想要在第二个循环中执行的操作是在结尾处删除换行符,请使用chomp函数。有了这个你不需要你的第二个循环。 (它也比使用正则表达式更快。)

# remove newlines for all array elements before doing anything else with it
chomp @filedata;

# .. or you can do it in your first loop
foreach $seq (@filedata){
    chomp $seq;
    if ($seq =~ /^>/) {
    ...
}

附加提示:如果文件很大,使用get_file_data1将整个文件读入数组可能会很慢。在这种情况下,最好在你去的时候遍历文件:

open my $FILE_DATA, $filename or die "Cannot open file \"$filename\"\n";
while (my $line = <$FILE_DATA>) {
    chomp $line;
    # process the record as in your Procedure section
    ...
}
close $FILE_DATA;

答案 1 :(得分:-1)

你的正则表达式专门捕获到1美元,但是你要在文件中打印$ _。结果很可能不是你想要的。

答案 2 :(得分:-1)

小心s ///中字符组的'*'或'贪婪'修饰符。你通常想要'+'。 '*'也会匹配不包含任何字符的行。

带有'g'修饰符的搜索表达式也可以计算字符数。像这样:

$perl -e '$a="aggaacaat"; $b = $a =~ s/[a]//g; print $b; '
5

非常酷!或者,在您的代码中,您可以只针对$ 1调用length()。

在你的正则表达式中看到逃脱的'/ n'我吃了一惊。虽然它工作正常,但常见的“行尾”搜索字词为“$”。这样更便携,不会弄乱你的角色数。