使用tr ///运算符计算字符串中的字母

时间:2012-03-14 19:48:58

标签: string perl count

我想在序列或字符串中计算A,C和G的数量。我写了以下代码。

但是当我打印这些值时,只有A打印出来。 C和G显示为零。 在下面的代码中我首先评估A,但是如果我通过首先评估C来切换顺序,我得到C的值,但是现在A和G被打印为零。

有谁能告诉我我的代码有什么问题?谢谢!

#! /usr/bin/perl

use strict;
use warnings;

open(IN, "200BP_junctions_fasta.faa") or die "Cannot open the file: $!\n";
while(<IN>) 
    next if $_ =~ /\>/;
    my $a = ($_ = tr/A//);
    my $c = ($_ = tr/C//);
    my $g = ($_ = tr/G//);
    print "A:$a, C:$c, G:$g\n";
}

该文件如下所示:

> A_Seq  
ATGCTAGCTAGCTAGCTAGTC  
> B_Seq  
ATGCGATCGATCGATCGATAG  

4 个答案:

答案 0 :(得分:6)

将您的$_ = tr/更改为$_ =~ tr/。此外,您错过了while的开放式大括号。

答案 1 :(得分:1)

因为'5'中没有'C''G' s。您分配 $_$_的翻译价值。如果绑定$_ =~ tr//)操作$_,您将获得所需的结果。

但是你真的不需要绑定到上下文变量。绑定是为了将正则表达式或转换操作应用于另一个变量。你写得更好:

my $a = tr/A//;
my $c = tr/C//;
my $g = tr/G//;

但你也可以这样做:

$_{$_}++ foreach m/[ACG]/g;
say "A:$_{A}, C:$_{C}, G:$_{G}";

答案 2 :(得分:1)

答案是您需要绑定运算符=~而不是赋值operat0r,=,或者您不需要绑定默认变量。

最近,我一直在使用printf来做这些事情:

while( <DATA> ) {
    next if /\>/;
    printf "A:%s C:%s G:%s\n", tr/A//, tr/C//, tr/G//;
    }

我经常希望tr///可以插值,所以我可以写这个,这不起作用:

while( my $line = <DATA> ) {
    next if $line =~ /\>/;
    print "Line is $_\n";
    printf "A:%s C:%s G:%s\n", map { $line =~ tr/$_// } qw(A C G);
    }

请注意,如果我在$_中使用了默认变量,我会对碰撞while产生额外的烦恼。我知道我可以做一个eval,但这不仅仅是一个麻烦,而是l4m3:

while( my $line = <DATA> ) {
    next if $line =~ /\>/;
    print "Line is $_\n";
    printf "A:%s C:%s G:%s\n", map { eval "\$line =~ tr/$_//" } qw(A C G);
    }

我不应该知道实现细节,所以我可以把它移到一个子程序,直到我能弄清楚如何摆脱eval,虽然额外的子程序调用可能会减慢大数据改写(munging):

while( my $line = <DATA> ) {
    next if $line =~ /\>/;
    print "Line is $line\n";
    printf "A:%s C:%s G:%s\n", map { count_bases( $line, $_ ) } qw(A C G);
    }

sub count_bases { eval "\$_[0] =~ tr/$_[1]//" }

如果你不喜欢tr///,可能有一些巧妙的XOR字符串方法,但我从来没有追求它足够长的时间来解决它(不是说它会比你已经做的更好)

答案 3 :(得分:0)

open(IN, "input") or die "Cannot open the file: $!\n";
while(<IN>) {
  next if $_ =~ /\>/;
  my $a = @{[m/(A)/g]};
  my $c = @{[m/(C)/g]};
  my $g = @{[m/(D)/g]};
  print "A:$a, C:$c, G:$g\n";
}