我正在尝试学习perl并在我的研究中使用它。我需要做一个简单的任务,即在一个文件中计算序列的数量及其长度,如下所示:
>sequence1
ATCGATCGATCG
>sequence2
AAAATTTT
>sequence3
CCCCGGGG
输出应如下所示:
sequence1 12
sequence2 8
sequence3 8
Total number of sequences = 3
这是我写的代码,非常粗糙和简单:
#!/usr/bin/perl
use strict;
use warnings;
my ($input, $output) = @ARGV;
open(INFILE, '<', $input) or die "Can't open $input, $!\n"; # Open a file for reading.
open(OUTFILE, '>', $output) or die "Can't open $output, $!"; # Open a file for writing.
while (<INFILE>) {
chomp;
if (/^>/)
{
my $number_of_sequences++;
}else{
my length = length ($input);
}
}
print length, number_of_sequences;
close (INFILE);
如果你能给我一些提示,我会很感激,例如,在else块中,当我使用长度函数时,我不确定我应该传递给它的论点。
提前致谢
答案 0 :(得分:1)
您只是打印出最后一个长度,而不是每个序列长度,并且您想要随时捕获序列名称:
#!/usr/bin/perl
use strict;
use warnings;
my ($input, $output) = @ARGV;
my ($lastSeq, $number_of_sequences) = ('', 0);
open(INFILE, '<', $input) or die "Can't open $input, $!\n"; # Open a file for reading.
# You never use OUTFILE
# open(OUTFILE, '>', $output) or die "Can't open $output, $!"; # Open a file for writing.
while (<INFILE>) {
chomp;
if (/^>(.+)/)
{
$lastSeq = $1;
$number_of_sequences++;
}
else
{
my $length = length($_);
print "$lastSeq $length\n";
}
}
print "Total number of sequences = $number_of_sequences\n";
close (INFILE);
答案 1 :(得分:1)
由于您已表明需要对程序提供反馈,因此请执行以下操作:
my ($input, $output) = @ARGV;
open(INFILE, '<', $input) or die "Can't open $input, $!\n"; # Open a file for reading.
open(OUTFILE, '>', $output) or die "Can't open $output, $!"; # Open a file for writing.
就我个人而言,我认为在处理简单的输入/输出文件关系时,最好只使用菱形运算符和标准输出。这意味着您从特殊文件句柄<>
读取,通常称为“菱形运算符”,并打印到STDOUT,这是默认输出。如果要将输出保存在文件中,只需使用shell重定向:
perl program.pl input.txt > output.txt
在这部分:
my $number_of_sequences++;
您正在创建一个新变量。离开块{ .... }
后,此变量将超出范围,在这种情况下:if-block。
在这部分:
my length = length ($input);
你忘了$
sigil了。您还在文件名上使用length
,而不是您阅读的行。如果要从输入中读取一行,则必须使用文件句柄:
my $length = length(<INFILE>);
虽然这也包括长度的换行符。
在这里你再次忘记了这些印记:
print length, number_of_sequences;
当然,这不会产生预期的输出。它将打印类似sequence112
的内容。
建议:
while (<>)
循环读取您的输入。这是惯用的方法。$.
。虽然请记住,它也会计算“坏”行,如空行或标题。使用您自己的变量将允许您考虑这些事情。chomp
该行。或者使用仅计算所需字符的替代方法:my $length = ( <> =~ tr/ATCG// )
这将读取一行,计算字母ATGC,返回计数并丢弃读取行。要点:
use strict;
use warnings; # always use these two pragmas
my $count;
while (<>) {
next unless /^>/; # ignore non-header lines
$count++; # increment counter
chomp;
my $length = (<> =~ tr/ATCG//); # get length of next line
s/^>(\S+)/$1 $length\n/; # remove > and insert length
} continue {
print; # print to STDOUT
}
print "Total number is sequences = $count\n";
请注意这里使用continue
,这样我们就可以跳过一条我们不想处理的行,但仍会打印出来。
正如我上面所说,如果你愿意,你可以将它重定向到一个文件。
答案 2 :(得分:0)
对于初学者,您需要将内循环更改为:
...
chomp;
if (/^>/)
{
$number_of_sequences++;
$sequence_name = $_;
}else{
print "$sequence_name ", length($input), "\n";
}
...
请注意以下事项:
my
声明已从$number_of_sequences
$sequence_name
中捕获。稍后在读取下一行时使用它。要使脚本在严格模式下运行,您可以在循环的<{1}}和my
之外添加$number_of_sequences
声明:
$sequence_name
my $sequence_name;
my $number_of_sequences = 0;
while (<INFILE>) {
...(as above)...
}
print "Total number of sequences: $number_of_sequences\n";
关键字声明一个新的词法范围变量 - 即一个仅存在于某个代码块中的变量,每次输入该代码块时,都会生成一个新版本该变量的创建。由于您希望将my
的值从一个循环迭代延续到下一个循环迭代,因此需要将$sequence_name
置于循环之外。
答案 3 :(得分:0)
#!/usr/bin/perl
use strict;
use warnings;
my ($file, $line, $length, $tag, $count);
$file = $ARGV[0];
open (FILE, "$file") or print"can't open file $file\n";
while (<FILE>){
$line=$_;
chomp $line;
if ($line=~/^>/){
$tag = $line;
}
else{
$length = length ($line);
$count=1;
}
if ($count==1){
print "$tag\t$length\n";
$count=0
}
}
close FILE;