2013-10-11 81 views
0

我正在嘗試編寫一個腳本,該腳本根據先前生成的文件搜索BLAST輸出,從而得到每個GI號碼的基因組位置。但是,我得到了與關閉IF語句相關的三個語法錯誤。作爲Perl的新手,我不知道如何解決這個問題。誰能幫我?我已經複製了代碼並標記了違規的右花括號。我做了一個快速檢查,確保所有分隔符均衡。perl - 關閉if語句時的語法不正確

#!/usr/bin/perl -w 

#decided to have input file entered in command line 
#call program followed by genome name. 
#the program assumes that a file with the extensions ptt and faa exist in the same dirctory. 


#####INPUT Name of multiple seq file containing ORF of genome, open file and assign IN filehandle ############# 

unless(@ARGV==2) {die "usage: perl nucnums.pl BLAST_output_filename query.ref subject.ref\n\nSubject is the database you made with FormatDB or MakeBlastDB.\n\nQuery is the other file";} 

$blastname=$ARGV[0]; 
$queryname=$ARGV[1]; 
$subjectname=$ARGV[2]; 
@nameparts=split(/\./, $blastname); 
$ofilename="$blastname[0]"."pos"; 
open(INBLAST, "< $blastname") or die "cannot open $blastname:$!"; 

open(OUT, "> $ofilename") or die "cannot open $ofilename:$!"; 
$line=<INBLAST>; 
print OUT $line; 
while (defined ($line=<INBLAST>)){ # read through rest of table line by line 
    if ($line=/^g/){ 
     @parts=split/\t/,$line; 
     @girefq=split/\|/,$parts[0]; 
     $ginumq = ($girefq[1]); 
     $postartq = $parts[6]; 
     @girefs=split/|/,$parts[1]; 
     $ginums = ($girefs[1]); 
     $postarts = $parts[8]; 
     open(INQUER, "< $queryname") or die "cannot open $queryname:$!"; 
     open(INSUBJ, "< $subjectname") or die "cannot open $subjectname:$!"; 
     SCOOP: while (defined ($locq=<INQUER>)){ 
      @locsq=split/\t/,$locq 
      if $locsq[0] = $ginumq{ 
       $posq = $locsq[1] + $postartq - 1; 
       } # <- Syntax error 

      } 
     close(INQUER); 
     SLOOP: while (defined ($locs=<INSUBJ>)){ 
      @locsq=split/\t/,$locs 
      if $locss[0] = $ginums { 
       $poss = $locss[1] + $postarts - 1; 
       } # <- Syntax error 

      } 
     close(INSUBJ); 
     print "$ginumq at position $posq matches with $ginums at position $poss \n" or die "Failed to find a match, try changing the order of the REF files"; 
     print OUT "$ginumq\t$posq\t$ginums\t$poss\t$parts[2]\t$parts[3]\t$parts[4]\t$parts[5]\t$parts[6]\t$parts[7]\t$parts[8]\t$parts[9]\t$parts[10]\t$parts[11]\t$parts[12]\n"; 
     } # <- Syntax error 
    } 

close(OUT); 
close(INBLAST); 
+2

除非'@ ARGV'爲2,然後再查找第三個參數('$ ARGV [2]',「subject.ref」),否則您即將死亡。如果有'$ ARGV [2]',那麼'@ ARGV'將是3,而不是2.它是數組的大小,而不是最後一個元素的索引。 –

回答

2

你需要改變:

@locsq=split/\t/,$locs 
if $locss[0] = $ginums { 

喜歡的東西:

@locsq=split/\t/,$locs; 
if ($locss[0] == $ginums) { 

也是一樣的$locsq[0]。如果您要比較字符串而不是數字,請使用eq而不是==

更新:感謝Zaid指出缺少的分號。

+1

而前面的行缺少分號 – Zaid

+0

更新了我的答案。謝謝。 – toolic

+1

這是正確的答案。圍繞'if'語句條件的括號在Perl中是必需的,就像它們在C中一樣(儘管Perl也需要在身體周圍使用花括號,但它們有點多餘)。 –

2
@locsq=split/\t/,$locs 
if $locss[0] = $ginums { 
    $poss = $locss[1] + $postarts - 1; 
} # <- Syntax error 

你得到一個誤導性的錯誤消息,因爲這裏的第一部分在語法上是有效的,但不是你想什麼。在第一行的缺少的分號意味着上述第一部分被解析爲一個後綴if(因爲在後綴if條件不需要括號內):

@locsq=split/\t/,$locs if $locss[0] = $ginums 

更重要的是,該部分起始$ginums{被解析爲對散列元素的引用。 (有沒有%ginums哈希值,但該錯誤會後報任何語法錯誤):

@locsq=split/\t/,$locs if $locss[0] = $ginums{$poss = $locss[1] + $postarts - 1;} 

其中$poss = $locss[1] + $postarts - 1;被作爲哈希鍵。

由於}之前的分號,您只會收到語法錯誤消息。如果你遺漏了這個分號,你可能會收到關於%ginums不存在的投訴(假設你有use strict; use warnings;;否則你可能根本沒有得到警告)。

這是其中一個錯字可以將一段代碼轉換爲有效的代碼(或者,在這種情況下,幾乎可以代替)但這並不意味着您想要的任何內容。

在第一行的末尾添加一個分號,並將if條件加括號。

1

看起來你已經編寫完整的程序,然後再做任何測試。那不是要走的路。你應該編寫小的章節,並測試它們在添加或組裝成完整的程序之前獨立工作。

use warnings優於將-w放在#!行上。

如果您在程序的頂部添加了use strict並且使用my聲明瞭所有變量,本程序中也會出現一些錯誤。例如,你寫

$ofilename = "$blastname[0]" . "pos"; 

但是沒有@blastname數組。 $ofilename最終總是隻包含pos,但use strict不會讓你在這種情況下運行程序。

您也寫(我推測應該是)

my @locsq = split /\t/, $locs; 
    if ($locss[0] = $ginums) { 
    $poss = $locss[1] + $postarts - 1; 
    } 

,並再次,沒有@locss陣列,所以這if永遠不會被執行,除非$ginums是一個空字符串。

我推薦你至少看看這個重寫你的程序,它使用了普遍接受的良好實踐,我希望你會同意更具可讀性。

您的最終print聲明存在問題,因爲控制檯的print始終返回true,因此die將永遠不會執行,但我對於解決該問題所做的操作不夠了解。

use strict; 
use warnings; 

unless (@ARGV == 2) { 
    die <<END; 
usage: perl nucnums.pl BLAST_output_filename query.ref subject.ref 

Subject is the database you made with FormatDB or MakeBlastDB. 

Query is the other file 
END 
} 

my ($blastname, $queryname, $subjectname) = @ARGV; 
my @nameparts = split /\./, $blastname; 
my $ofilename = "${blastname}pos"; 

open my $inblast, '<', $blastname or die "cannot open $blastname: $!"; 
open my $out,  '>', $ofilename or die "cannot open $ofilename: $!"; 
print $out scalar <$inblast>; 

while (my $line = <$inblast>) { 

    next unless $line =~ /^g/; 

    my @parts = split /\t/, $line; 
    my @girefq = split /\|/, $parts[0]; 
    my $ginumq = $girefq[1]; 
    my $postartq = $parts[6]; 
    my @girefs = split /|/, $parts[1]; 
    my $ginums = $girefs[1]; 
    my $postarts = $parts[8]; 

    my ($posq, $poss); 

    open my $inquer, '<', $queryname or die "cannot open $queryname: $!"; 
    while (my $locq = <$inquer>) { 
    my @locsq = split /\t/, $locq; 
    if ($locsq[0] = $ginumq) { 
     $posq = $locsq[1] + $postartq - 1; 
    } 
    } 
    close($inquer); 

    open my $insubj, '<', $subjectname or die "cannot open $subjectname: $!"; 
    while (my $locs = <$insubj>) { 
    my @locss = split /\t/, $locs; 
    if ($locss[0] = $ginums) { 
     $poss = $locss[1] + $postarts - 1; 
    } 
    } 
    close($insubj); 

    print "$ginumq at position $posq matches with $ginums at position $poss \n" 
     or die "Failed to find a match, try changing the order of the REF files"; 

    print $out join("\t", $ginumq, $posq, $ginums, $poss, @parts[2..12]), "\n"; 


} 

close $inblast; 
close $out or die $!;