2015-09-02 198 views
1

我在下面編寫了一個腳本來分析bedtools(-tab選項,-name選項)中的兩種文件格式,以便在序列匹配時組合標題。我遇到的問題是,如果序列與多個名稱匹配,它只會打印與其對應的名稱之一。我想知道是否有人提出瞭如何解決這個問題的建議。因爲我想要序列和名字的位置。是否有牀墊選項?foreach循環不返回預期結果

我的腳本將這兩個文件存儲到它們自己的散列中,然後通過它們循環,如果它們相等,則假設打印出具有適當名稱的序列中的匹配項。它這樣做,但如果多個序列對應於名稱,它不會出錯,它只是不打印它們。所以我的結論是,foreach循環以某種形式失敗的語法明智,我沒有注意到。有什麼建議麼?乾杯。

採樣數據:-name輸出bedtools

 >sequence_a 
    AGGT 
    >sequence_b 
    AAAA 
    >sequence_c 
    CCCC 
    >sequence_d 
    AAAA 

採樣數據:-Tab輸出bedtools

>1-5 
    AAAA 
    >10-14 
    ACCT 
    >15-19 
    CCCC 
從腳本預期輸出

>sequence_b|1-5 
    AAAA 
    >sequence_c|15-19 
    CCCC 
    >sequence_d|1-5 
    AAAA 

腳本

my %sequence; 

open(NAMES_FILE, $ARGV[0]) or die "Cannot open the file: $!"; 
my $hash_key_name; 
my $hash_value_name; 
while (my $line = <NAMES_FILE>) { 
    if ($line =~ /^>(\S+)/) { 
    $hash_key_name = $1; 
    } 
    elsif ($line =~ /\S/) { 
    chomp $line; 
    $hash_value_name = $line; 
    $sequence{$hash_key_name} = $hash_value_name; 
    } 
} 


my %sequence_2; 
open (POSITIONS_FILE, $ARGV[1]) or die "Cannot open the file: $!"; 
my $hash_key_pos; 
my $hash_value_pos; 
while (my $line2 = <POSITIONS_FILE>) { 
    if ($line2 =~ /^>(\S+)/) { 
    $hash_key_pos = $1; 
    } 
    elsif ($line2 =~ /\S/) { 
    chomp $line2; 
    $hash_value_pos = $line2; 
    $sequence_2{$hash_key_pos} = $hash_value_pos; 
    } 
} 


foreach $hash_key_pos (keys %sequence_2) { 
    foreach $hash_key_name (keys %sequence) { 
     if ($sequence{$hash_key_name} eq $sequence_2{$hash_key_pos}){ 
      print ">$hash_key_name|$hash_key_pos\n$sequence{$hash_key_name}\n"} 
    } 
} 
+0

我會想象你的散列鍵有問題,而不是你的語法。在每個循環中放置打印語句以查看哈希中的內容。特別是在最後一個循環中應該有一個'else'子句,並且當哈希不匹配時會顯示一條警告消息。 (我會大幅度重構這段代碼以減少重複次數和減少短暫變量,但這實際上超出了你的問題的範圍,也取決於你想用這段代碼去哪裏。) – tripleee

+0

最後一個循環尤其是效率非常低。如果你有一個像'$ hash {$ key} {「name」}'和$ hash {$ key} {「pos」}''這樣的所有密鑰的頂級散列,它會更加簡單和高效。 – tripleee

+0

我已經有了一個打印語句來檢查散列內容,爲了在這裏發佈我的腳本,我把它拿出來了。我很抱歉。 – serious

回答

1

哈希將愉快地覆蓋值,只保存最新值,而不會引發錯誤。如果你想抓住這一點,你需要在把一個明確的檢查,看是否哈希有一個值,你覆蓋它之前,是這樣的:

while (my $line = <NAMES_FILE>) { 
     if ($line =~ /^>(\S+)/) { 
      $hash_key_name = $1; 
     } 
     elsif ($line =~ /\S/) { 
      chomp $line; 
      $hash_value_name = $line; 
      if (defined($sequence{$hash_key_name}) && $sequence{$hash_key_name} ne $hash_value_name) { 
       die("multiple sequences match $hash_key_name: $sequence{$hash_key_name}, $hash_value_name"); 
      } 
      $sequence{$hash_key_name} = $hash_value_name; 
     } 
} 

話雖這麼說,這將是你最有幫助可以提供產生您想要捕捉的錯誤的示例數據。它看起來好像上面的數據不應該包含這個錯誤。

+0

由於序列太長,我無法上傳樣本數據。你如何建議我向你展示樣本數據? – serious

+0

我解決了我的問題!謝謝....我沒有意識到很多數據實際上是重複的......所以它只給了我一個回報......讓它看起來像我錯過了很多! 感謝您向我展示如何在出現錯誤時殺死某些東西。 (你的格式比我的要好得多) – serious

+0

謝謝。有一本名爲「Modern Perl」的書,現在已經是第二或第三版了,它可以幫助您快速掌握perl編程的最新技術,功能和習慣用法。 –