2013-07-05 38 views
0

我在網站周圍搜索,出乎意料地我似乎找不到可以工作的東西爲我的特殊問題。所以我想我會發布它,看看你們中有些更有經驗的程序員如何解決問題。在一個文件/數組中,搜索散列鍵,並用散列值替換它,對所有散列鍵/值執行此操作。

我有一個文本文件,電子表格(多行與製表符分隔列),我想通過某些標籤(例如scaffold1253.1_size81005.6.32799_7496)進行搜索,並用更簡單的標籤(例如scaffold1253替換它們。 1a)中。這些標籤僅位於文本文件的第一列。我已經編寫了這個腳本,以便將舊標籤的散列作爲與新標籤對應的鍵作爲其各自的值。這個散列有大約26000行。所以基本上我想將散列鍵1乘1,在文本文件中搜索它們,並用它們各自的散列值替換它們。

我有一個相當不錯的服務器可用,所以如果它太複雜,使其第一列專門加快過程,那就沒關係。

這是我到目前爲止有:

use warnings; 



$gtf = './Hc_genome/Hc_rztk_1+2+8+9.augustus.gtf'; 
    open(FASTAFILE2, $gtf); 
    @gtfarray = <FASTAFILE2>; 
    #print @gtfarray; 


my %hash; 
while (<>) 
{ 
    chomp; 
    my ($key, $val) = split /\t/; 
    $hash{$key} .= exists $hash{$key} ? ",$val" : $val; 
} 

#print %hash; 

while (my ($find, $replace) = each %hash) { 
    foreach (@gtfarray){ 
     $_ =~ s/$find/$replace/g; 
     push @newgtf, $_; 
    } 
} 
print @newgtf; 

此代碼似乎並不工作,因爲它沒有完成。我很確定這是foreach循環結構的問題。對不起,我不知道有任何其他方式來做到這一點。有沒有人有更好的方式來運行這個文件並進行更換?

任何輸入將不勝感激! 謝謝,

安德魯

@DVK

這裏是您的MODS的完整的腳本,以你的while循環,任何想法,爲什麼它不接受它運行到語法錯誤?再次感謝!

use warnings; 

$gtf = './Hc_genome/Hc_rztk_1+2+8+9.augustus.gtf'; 
    open(FASTAFILE2, $gtf); 

my %hash; 
while (<>){ 
    chomp; 
    my ($key, $val) = split /\t/; 
    $hash{$key} .= exists $hash{$key} ? ",$val" : $val; 
} 


while $line (<FASTAFILE2>){ 
    my @fields = split(/\t/, $line); 
    # If you only care about first column, don't need the foreach loop below; 
    # just do the loop insides on $fields[0] 
    foreach my $field (@fields) { 
     $field = $hash{$field} if exists $hash{$field}; 
     print $outfile "$field\t"; # Small bug - will print training \t 
    } 
    print $outfile "\n" 
} 

__END__ 

下面是語法錯誤: 的perl在gtf_mod2.pl線14 gtf_mod2.pl < ./Hc_genome/header_file.txt 語法錯誤,接近 「而$線」 在gtf_mod2.pl線 語法錯誤23,在「}」 附近執行gtf_mod2.pl由於編譯錯誤而中止。

+0

你必須把''一樣,而(我的$線= )' –

回答

1

第一次通過循環使用初始的$find$replace鍵/值對耗盡文件。

有兩種可能的解決方案:

  1. 打開期間每個迭代while循環(昂貴的)
  2. 移動foreach循環的同時,外部和迭代讀取文件哈希各時間(較便宜)

例如:

REPLACE: 
for my $line (@gtfarray) { 
    while(my ($find, $replace) = each %hash) { 
     if($line =~ s/$find/$replace/g) { 
     push @newgtf, $line; 
     next REPLACE; # skip to next iteration 
     } 
    } 
    # if there was no replacement, push the old line 
    push @newgtf, $line 
} 
+0

感謝您的答案的括號內$ line'。我現在正在運行它。正在修改的gtf文件長度約爲315000行,因此可能需要一段時間。我會讓你知道結果如何。我也在嘗試下面的建議,因爲他們的做法與之相反,他建議大文本文件應該花費更少的時間。 – amrezans

1

您要替換第一列的文件有多大?

如果是> 50,000行,你最好做反向:通過散列文件

  • 迭代一次,那散列

  • 迭代存儲在內存中,通過主文件一次,併爲每行,每列,發現在記憶的哈希值,如果發現散列值替換,並寫。

換句話說,除去第一@gtfarray = <FASTAFILE2>;,代之以你最後while循環:

while my $line (<FASTAFILE2>) { 
    my @fields = split(/\t/, $line); 
    # If you only care about first column, don't need the foreach loop below; 
    # just do the loop insides on $fields[0] 
    foreach my $field (@fields) { 
     $field = $hash{$field} if exists $hash{$field}; 
     print $outfile "$field\t"; # Small bug - will print training \t 
    } 
    print $outfile "\n"; 
} 

注:我做一個假設,即字段包含的散列鍵的全部內容(如您的數據文件將包含與「scaffold1253.1_size81005.6.32799_7496」,而不是一個字段的字段與「XYZscaffold1253.1_size81005.6.32799_7496 ___ IOU」)。

如果這個假設是錯誤的,並且確實需要運行正則表達式,因爲腳手架字符串可能包含在更長的字符串中,除了運行O(N * M)正則表達式之外,還可能有更好的解決方案:如果腳手架串都是有一定知名度定義的格式(例如,「scaffoldNNNNN.NNN_sizeNNNNN.NNN.NNNN_NNNN」)的,你需要做的又是什麼:

  • 對於數據文件的每一行,運行一個單一的正則表達式發現,圖案,整個圖案在捕獲組圓括號內:

    @matches = ($line =~ m/(scaffold\d+\.\d+_size\d+\.\d+\.\d+_\d+/g); 
    
  • 然後,在散列中查找@matches數組的每個值。如果找到,只運行匹配s ///正則表達式。

+0

他說,搜索值來代替在第一欄,我想,所以我覺得'foreach'循環是不必要的 - 只是檢查'$域[0]'。 –

+0

@ChrisCharley - 我很困惑,無論是他的意思是數據文件或散列文件中的第一列。好點子。 – DVK

+0

對不起,是的,它是包含舊標籤的數據文件的第一列(由製表符分隔的列),這些舊標籤需要被新標籤替換。 – amrezans

0

難道這是Tie::File的工作嗎?假設,也就是說,數據文件可以作爲一個數組來操作。

use Tie::File; 

my $file = "./Hc_genome/Hc_rztk_1+2+8+9.augustus.gtf"; 

tie @lines, 'Tie::File', $file or die ; 
for (@lines) { 
s/Oldlabel/NewLable/g; # Change this to fit 
} 

untie @lines ; 

Tie::File做了一堆花樣,以保持「到位」更改文件存儲效率。

0

看着你previous post,那豈不是更簡單的創建縮短的「身份證」,而讀取文件。那麼你會不需要其他文件,你得到你的散列?

這裏是(未測試)下面的代碼。 (需要將打印語句指向命令行上的輸出文件或打開文件以寫入腳本)。

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

my $gtf = './Hc_genome/Hc_rztk_1+2+8+9.augustus.gtf'; 
open my $FASTAFILE2, "<", $gtf or die "Unable to open '$gtf' for reading. $!"; 

my %seen; 

while (<$FASTAFILE2>) { 
    chomp; 
    my ($id, $val) = split /\t/, $_, 2; 

    # copy $id to $prefix and 
    # remove everything after '.1' in $prefix 
    (my $prefix = $id) =~ s/\.1\K.*//; 

    if ($seen{$id}) { 
     ++$seen{$id}; 
    } 
    else { 
     $seen{$id} = 'a'; 
    } 
    print "$prefix$seen{$id}\t$val\n"; 
} 

close $FASTAFILE2 or die "Unable to close '$gtf' from reading. $!"; 
+0

嗯,所以事情是,我仍然需要在最後通過代碼創建的文件張貼在自己的。而且,在上一篇文章中使用的文件中的一些腳手架在文本/ gtf文件中跳過。所以我相信這會導致一些腳手架被貼上早先字母的字母,而不是它們應該是的。所以我不得不用哈希導入適當的標籤。基本上這個gtf文件在前一篇文章的基因組中包含註釋的基因,並且缺少一些標籤/支架,僅僅是因爲有一些沒有註釋基因的支架!希望有道理;) – amrezans