计算文件中以用户定义的匹配开头和结尾的序列

时间:2018-04-20 16:29:39

标签: regex perl fasta

我有一个称为“test.fas”的DNA序列的fasta格式文件:

>test1
GCCATTACAGAACATCAGTCACAGTACGTACTGTGTTCTGCCGTGCTGTCTA
>test2
CGGATGAAGCGCCAATCGTACGTACAATAAGTTGCCTAAAGTGTTTCA
>test3
ATGCATGCATGC

我还有一个名为“primer.txt”的制表符分隔的引物序列文件:

GCCATTACAGAACATCAGTCACA TAGACAGCACGGCAGAACAC
CGGATGAAGCGCCAATC   TGAAACACTTTAGGCAACTTATT

此primer.txt文件中的每一行都是一个引物对,可以匹配fasta文件中序列的开头和结尾。每行上的第二个引物也需要反向补充才能匹配fasta文件中的任何内容。查看primer.txt第一行的第一个引物对,在反向补充第二个引物后,它应该与test.fas文件中test1的序列匹配。

我希望能够做的是将这两个文件提供给perl程序,并获取一个计数的输出文件,其中包含来自primer.txt文件的引物对找到序列的次数。在这种情况下,我的outfile将列出:

1
1

实际上,我在文件中有650000个序列,170个引物集用于从文件中搜索和枚举。因此,我想要一个170行长的outfile,每行列出在该特定引物对的fasta文件中找到匹配的次数。基本上,对于primer.txt文件中的每一行,计算序列在fasta文件中以该引物对开始和结束的次数。这是我到目前为止所提出的:

#!/usr/bin/perl
use strict;
use warnings;

print "Name of the FASTA file: ";
chomp( my $multifasta = <STDIN> );

print "Name file with primers: ";
chomp( my $pulls = <STDIN> );

print "Name of the output file: ";
chomp( my $out = <STDIN> );

open(MULTIFASTA,$multifasta) || die ;
  my $seq = do { local $/; <MULTIFASTA>};
  close MULTIFASTA;

open(PULLS,$pulls) || die;
  while (my $line = <PULLS>){
  chomp $line;
  my @primers = split (/\t/,$line);
  my $revcomp = reverse $primers[1];
  $revcomp =~ tr/ATGCatgc/TACGtacg/;  #reverse complement the reverse primer
  my $matches = () = $seq =~ /^\Q$primers[0].*\Q$primers[1]$/; #How to structure the regex? 
  open(OUTFILE,">>$out");
  print OUTFILE "$matches\n";   
}

我的outfile最终得到了这个:

0
0

我显然有些事搞砸了。我正在迅速陷入尝试我在Google上找到的不同事物的陷阱,而没有牢牢掌握对代码做了什么,此时我迷失了。这是很快就需要答案的结果,并且对编程知之甚少。我从阅读中收集到我应该在整个文件中读取以使用本地扫描匹配,我需要使用\ Q在perl中的正则表达式中搜索变量。无论如何,任何帮助或指针将非常感激。谢谢 -

2 个答案:

答案 0 :(得分:2)

从所有引物创建一个正则表达式。另外,将引物存储在散列中,值将是行号。然后,遍历fasta文件并尝试匹配正则表达式。如果匹配,则使用哈希检索引物的行号,并使用另一个哈希记录每个行号的匹配数。最后,只需报告数字:

#!/usr/bin/perl
use warnings;
use strict;

my ($fasta_file, $primers_file) = @ARGV;

my %primer;
open my $primers_fh, '<', $primers_file or die $!;
while (<$primers_fh>) {
    chomp;
    my ($first, $second) = split /\t/;
    $second = reverse $second;
    $second =~ tr/actgACTG/tgacTGAC/;
    undef $primer{$first}{$.};
    undef $primer{$second}{$.};
}

my $primers_count = $.;
my $regex =  join '|', keys %primer;

my %seen;
open my $fasta_fh, '<', $fasta_file or die $!;
while (<$fasta_fh>) {
    if (/^($regex)/) {
        ++$seen{$_} for keys %{ $primer{$1} };
    }
}

for my $line_number (sort { $a <=> $b } 1 .. $primers_count) {
    print $seen{$line_number} // 0, "\n";
}

答案 1 :(得分:1)

我认为你误解了\Q(和\E)的作用。它用于自动反斜杠正则表达式特殊字符。它不是“在正则表达式中搜索变量”。 Perl已经在本地识别正则表达式中的变量。您在此处不需要\Q

my $matches = () = $seq =~ /^\Q$primers[0].*\Q$primers[1]$/;

像这样的基本正则表达式匹配返回1或0表示true和false。它不会像你想要的那样返回一系列匹配。你需要g全局修饰符。

您可能还需要使用.*代替.*?非贪婪。

您在这里也错误地使用了^$。这会强制您的引物仅在(多行)字符串的开头和结尾处匹配,而不是与其中的行匹配。这就是为什么你的比赛得到0(假)。