0

我是 Perl 正则表达式的新手,所以我很感激任何帮助。我正在解析 BLAST 输出。现在,我只能解释 e 值仅包含整数和小数的命中。如何在电子值采用科学计数法的情况下包含命中?

爆炸输出.txt

                                                               Score     E
Sequences producing significant alignments:                       (Bits)  Value

ref|WP_001577367.1|  hypothetical protein [Escherichia coli] >...  75.9    4e-15
ref|WP_001533923.1|  cytotoxic necrotizing factor 1 [Escherich...  75.9    7e-15
ref|WP_001682680.1|  cytotoxic necrotizing factor 1 [Escherich...  75.9    7e-15
ref|ZP_15044188.1|  cytotoxic necrotizing factor 1 domain prot...  40.0    0.002
ref|YP_650655.1|  hypothetical protein YPA_0742 [Yersinia pest...  40.0    0.002

ALIGNMENTS
>ref|WP_001577367.1| hypothetical protein [Escherichia coli]

解析.pl

open (FILE, './blastoutput.txt');
my $marker = 0;
my @one;
my @acc;
my @desc;
my @score;
my @evalue;
my $counter=0;
while(<FILE>){
   chomp;
   if($marker==1){
   if(/^(\D+)\|(.+?)\|\s(.*?)\s(\d+)(\.\d+)? +(\d+)([\.\d+]?) *$/) {
   #if(/^(\D+)\|(.+?)\|\s(.*?)\s(\d+)(\.\d+)? +(\d+)((\.\d+)?(e.*?)?) *$/) 
            $one[$counter] = $1;
            $acc[$counter] = $2;
            $desc[$counter] = $3;
            $score[$counter] = $4+$5;
            if(! $7){
                $evalue[$counter] = $6;
            }else{
                $evalue[$counter] = $6+$7;
            }
            $counter++;
        }
    }
    if(/Sequences producing significant alignments/){
        $marker = 1;
    }elsif(/ALIGNMENTS/){
        $marker = 0;
    }elsif(/No significant similarity found/){
        last;
    }
}
for(my $i=0; $i < scalar(@one); $i++){
    print "$one[$i] | $acc[$i] | $desc[$i] | $score[$i] | $evalue[$i]\n";
}
close FILE;
4

3 回答 3

3

您可以将科学记数法中的数字(或不匹配)与此匹配:

\d+(?:\.\d+)?+(?:e[+-]?\d+)?+

使用您的代码:

if (/^([^|]+)\|([^|]+)\|\s++(.*?)\s(\d+(?:\.\d+)?+)\s+(\d+(?:\.\d+)?+(?:e[+-]?\d+)?+)\s*$/) {
    $one[$counter] = $1;
    $acc[$counter] = $2;
    $desc[$counter] = $3;
    $score[$counter] = $4;
    $evalue[$counter] = $5;
    $counter++;
}

(我添加了一些所有格量词++?+尽可能减少回溯步骤的数量,但第 3 组使用惰性量词。如果可能的话,最好的方法是在描述部分使用更精确的模式。)

于 2013-05-06T04:31:19.403 回答
0

您还可以避免匹配这些数字:

while(<FILE>){
    chomp;
    $marker = 0 if $marker and /ALIGNMENTS/;
    if($marker == 1 and my ($r, $w, $d) = split(/[|]/)) {
            my @v = split (/\s+/, $d);
            print "$v[-2]\t$v[-1]\n";
            # some processing ...
    }   
    $marker = 1 if /Sequences producing significant alignments/;
    last        if /No significant similarity found/;
}
于 2013-05-06T05:29:34.710 回答
0

如果这是使用 Perl 的作业或练习,那么请采纳其他一些建议并尝试找出最佳解决方案(但不要止步于此,您还会在 Internet 上找到很多内容,甚至还有书籍涵盖解析 BLAST 的主题!)。但在实践中,您永远不会希望以这种方式解析 BLAST 报告,因为您的代码将不可读,并且不能保证将来可以正常工作,因为普通报告格式可能会发生变化。

我强烈建议您坚持使用 XML 输出或制表符分隔的表格格式,并且只使用 BioPerlBio::SearchIO来解析您的报告。例如,如果您查看Bio::SearchIO HOWTO,您会发现在没有任何 Perl 知识的情况下选择报告的某些部分并按某些标准进行过滤非常容易。如果你想提出一个非 BioPerl 的解决方案,我建议你考虑制表符分隔的格式,以便将来让你自己更轻松(然后你可以以一种易于管理和可读的方式实现复杂的任务)。

于 2013-05-06T19:40:32.887 回答