使用perl计算特定文件格式的字符串长度

时间:2014-11-11 14:18:57

标签: perl

我正在尝试学习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块中,当我使用长度函数时,我不确定我应该传递给它的论点。

提前致谢

4 个答案:

答案 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;