Использование оператора tr /// для подсчета букв в строке - PullRequest
3 голосов
/ 14 марта 2012

Я бы хотел посчитать количество A, C и G в последовательности или строке.Я написал следующий код:

Но когда я печатаю значения, печатаются только буквы A.C и G отображаются как ноль.В приведенном ниже коде я вначале оцениваю букву А, но если я переключаю порядок, вычисляя сначала букву С, я получаю значения С, но теперь буквы А и 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 ]

6 голосов
/ 14 марта 2012

Измените $_ = tr/ на $_ =~ tr/. Кроме того, вам не хватает открытой скобки для вашего while.

1 голос
/ 15 марта 2012

Ответ, что вам нужен оператор привязки, =~ вместо присваивания 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, хотя дополнительные вызовы подпрограммы могут замедлить обработку больших данных:

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]//" }

Возможно, есть какой-то умный путь к строкам XOR, если вы этого не сделаетекак tr///, но я никогда не занимался этим достаточно долго, чтобы понять это (не то, чтобы это было лучше, чем то, что вы уже делаете).

1 голос
/ 14 марта 2012

Потому что '5' не содержит 'C' s или '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}";
0 голосов
/ 15 марта 2012
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";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...