2012-05-01 3 views
1

Я хочу подсчитать количество вхождений нуклеотидов (буквы «A, T, G, C» в строке). Я пытался использовать для этого оператор tr///, но он возвращает отсчет нуля каждый раз в приведенном ниже коде.Как подсчитать количество шаблонов с использованием переменных в tr /// -операторе?

Это происходит, только если я использую переменную внутри оператора tr///. Если я набираю отдельные буквы отдельно, он работает. Я хотел бы знать, можем ли мы использовать переменные внутри оператора tr/// для сопоставления шаблонов (и подсчета). И если мы можем, кто-то скажет мне, как изменить мой код.

Позже планирую подсчитать количество кодонов (~ 64). Отсюда проблема. Цените свое время. Благодаря!

#!/usr/bin/perl 

use strict; 
use warnings; 

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my @atgc = qw(A T G C); 
my %hash =(); 

foreach my $nt(@atgc) { 
    $hash{$nt} = ($orf =~ tr/$nt//); 
} 
+0

Параметр '' тр /// оператор работает на основе символ за символом. Это не поможет вам, если вы хотите считать кодоны. –

ответ

3
$hash{$nt} = eval "\$orf =~ tr/\Q$nt\E//" 

должен делать эту работу. Возможно, это не самое эффективное решение.

+0

Спасибо, что помогли. Можете ли вы рассказать мне, почему вы использовали обратную косую черту перед $ orf? – Jordan

+0

Чтобы получить действительный код Perl после интерполяции строки с двойными кавычками. –

4

Там нет экземпляра «$», «n» или «t» в «ATGCTAGCTAGCATAGAGCTAGCTA», таким образом, tr правильно возвращает ноль.

Если вы хотите создать оператора tr///, вам нужно будет его разобрать и скомпилировать.

my %counts; 
for my $nt (@atgc) { 
    $counts{$nt} = eval "\$orf =~ tr/\Q$nt\E//"; 
} 

Но я бы не использовал tr///.

my %atgc = map { $_ => 1 } @atgc; 
my %counts; 
++$counts{$nt} for grep $atgc{$_}, split //, $orf; 
4

К сожалению Perl не будет интерполировать переменную в списке поиска для tr///. Вы должны будете использовать регулярное выражение вместо:

use strict; 
use warnings; 

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my @atgc = qw(A T G C); 
my %count; 

$count{$1}++ while $orf =~ /([@atgc])/g; 

printf "%s => %d\n", $_, $count{$_} for @atgc; 

выход

A => 8 
T => 6 
G => 6 
C => 5 

Остерегайтесь

Это не - как это может показаться - общее решение для сопоставления любого из массива строк. То, что происходит, @atcg интерполируется в регулярное выражение, как если бы оно было в строке с двумя кавычками . Это означает, что Perl будет использовать встроенную переменную $" (установленную в одно пространство по умолчанию), чтобы превратить ее в строку, эквивалентную join $", @atgc.

Так что код на самом деле выглядит как

$count{$1}++ while $orf =~ /([A T G C])/g; 

, который будет соответствовать пространства, а также письма, и может сломаться в целом, если @atgc содержит все, что специальный внутри регулярного выражения класса символов, как ^, ] или -.

Недопустимое подсчет пробелов не должно быть проблемой, но если ваш список может содержать символы, это не решение, которое вы должны использовать.

Подсчет для каждого ASCII символ может быть записан безопасно, как

$count{$1}++ while $orf =~ /(.)/sg; 

и нежелательной информации в %count хэш может быть просто проигнорированы.

+2

Это также подсчет пробелов на входе. Это canl mess, если у вас есть '' '' '', '' ']" или '' '' в '@ atgc'. – ikegami

+0

Когда я использую код, я на самом деле получаю все в 4 раза. – Jordan

+0

@Anish: вы должны заменить весь цикл 'foreach' на эту строку кода. Мое решение стоит само по себе. Я обновил свой ответ, чтобы показать это более четко. – Borodin

1

Вы можете использовать s///g:

#!/usr/bin/env perl 

use strict; use warnings; 

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my @atgc = qw(A T G C); 

my %hash = map {$_ => $orf =~ s/$_/$_/g } @atgc; 

Выход:

--- 
A: 8 
C: 5 
G: 6 
T: 6

Если исходная строка будет очень долго, вы можете рассматривать его как держит содержимое некоторое время и прочитать одну байт в то время, когда символы гарантированы как ASCII.

#!/usr/bin/env perl 

use strict; use warnings; 

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my %atgc = map { $_ => undef } qw(A T G C); 

use YAML; 
print Dump count(\$orf, \%atgc); 

sub count { 
    my $src_ref = shift; 
    my $lookup = shift; 

    my %count; 

    open my $src, '<', $src_ref or die $!; 
    { 
     local $/ = \1; 
     exists $lookup->{$_} and $count{ $_ } += 1 while <$src>; 
    } 
    close $src; 

    return \%count; 
} 
1

Вам не нужны регулярные выражения и т.д., чтобы сделать это, вам просто нужно ходить строку:

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my %nt; 

$nt{$_}++ foreach (split('', $orf)); 
1

сделать шаблон компилятор.

sub make_counter { 
    my @sequences = @_; 

    my $pattern = "(?:" . join("|", map quotemeta, @sequences) . ")"; 

    my $compiled = eval q< 
    sub { 
     local($_) = @_; 
     my $n =() = /$pattern/g; 
    } 
    >; 

    if (defined $compiled) { 
    return $compiled; 
    } 
    else { 
    die "$0: internal: counter compilation failed:\[email protected]\n"; 
    } 
} 

С quotemeta, мы заставляем все символы в последовательности, чтобы соответствовать себя только без каких-либо специальных значений. Section 4 of the Perl FAQ описывает, что фанк бит для подсчета совпадений:

Другой вариант использует глобальный матч в контексте списка, а затем присваивает результат в скаляр, производя подсчет числа совпадений.

$count =() = $string =~ /-\d+/g; 

Обратите внимание, что она терпит мусор в вашей последовательности. Так, например, граф нуклеотиды с

my @nucleotides = qw/ G A T C /; 

my $numnuc = make_counter @nucleotides; 
print $numnuc->("xGxAxTxxxxTyA1C2A"), "\n"; 

Выход:

7

Count кодоны с

my @codons = qw(
    TTT TCT TAT TGT TTC TCC TAC TGC TTA TCA TAA TGA 
    TTG TCG TAG TGG CTT CCT CAT CGT CTC CCC CAC CGC 
    CTA CCA CAA CGA CTG CCG CAG CGG ATT ACT AAT AGT 
    ATC ACC AAC AGC ATA ACA AAA AGA ATG ACG AAG AGG 
    GTT GCT GAT GGT GTC GCC GAC GGC GTA GCA GAA GGA 
    GTG GCG GAG GGG 
); 

my $numcod = make_counter @codons; 
print $numcod->("GAG-GGG!AGG,TAT#TTT"); 

Обратите внимание, что любой мусор, если они присутствуют, должны произойти между кодонов последовательности.

Выход:

5
Смежные вопросы