我正在尝试用Perl编写来计算DNA序列中每个A / C / G / T碱基的数量。但无法弄清楚我的代码出了什么问题。 " ATCTAGCTAGCTAGCTA"是我给出的那种数据。
#!usr/bin/perl
use strict;
use warnings;
my $in_file = <$ARGV[0]>;
open( my $FH_IN, "<", $in_file );
my $dna = <$FH_IN>;
my $index = 0;
my ( $freq_a, $freq_c, $freq_g, $freq_t ) = 0;
my $dna_length = length($dna);
while ( $index < $dna_length ) {
my $base = substr( $dna, $index, 1 );
if ( $base eq "A" ) {
$freq_a++;
$index++;
next;
} elsif ( $base eq "C" ) {
$freq_c++;
$index++;
next;
} elsif ( $base eq "G" ) {
$freq_g++;
$index++;
next;
} elsif ( $base eq "T" ) {
$freq_t++;
$index++;
next;
} else {
next;
}
}
print "$freq_a\n$freq_c\n$freq_g\n$freq_t\n";
exit;
我知道有很多方法可以做到,但我想知道的是我做错了所以我可以从错误中吸取教训。
答案 0 :(得分:2)
Perl有一个特殊的文件句柄可用于解决这些问题:菱形运算符<>
。它将从文件名(如果提供)读取输入,如果不提供,则读取标准输入。
其次,既然您只对ACGT
感兴趣,也可以使用正则表达式/([ACGT])/g
来查找它们。
第三,使用散列是在Perl中计算字符的惯用方法:$count{A}++
所以你的脚本变成了:
use strict;
use warnings;
my %count;
while (<>) {
while (/([ACGT])/g) {
$count{$1}++;
}
}
print "$_\n" for @count{qw(A C G T)};
用法:
script.pl input.txt
答案 1 :(得分:1)
每次绕过循环时,在$dna_length
,$index
和$base
打印出来的值会很有帮助 - 在为{{1 }}
如果您将$base
的递增移动到循环的结尾($index
/ if
/ elsif
块之外),您的代码会更强大删除了所有else
语句。
另一种“快速修复”是在开始处理之前next
输入行。
答案 2 :(得分:1)
好的,到目前为止你做得很好,只有一个问题阻止你的程序工作。
这很明显,但从文件中读取的每一行最后都有一个换行符"\n"
。所以发生的事情是$index
到达字符串中的换行符,该换行符由else
子句处理(因为它不是A
,C
,G
或T
)只执行next
,因此会反复处理相同的字符。你的程序挂了,对吗?
您可以使用chomp
删除换行符,但正确的解决方法是在$index
子句中增加else
,就像处理所有其他字符一样。所以它看起来像
else {
++$index;
next;
}
正如您所怀疑的,有更好的方法来写这个。您的代码中还有其他一些恶意内容,但这种更改应该会让您暂时停止。