2015-05-23 92 views
0

我想使用其他文件中的信息修改phylip文件中的名稱。 phylip只是一個連續的信息串,我想要改變的名字(例如aaaaaaabyd)被嵌入其中。像這樣使用來自其他文件的信息修改文件

((aaaaaaabyd:0.23400159127856412500,(((aaaaaaaaxv:0.44910864993667892753,aaaaaaaagf:0.51328033054009691849):0.06090419044604544752,((aaaaaaabyc:0.11709094683204501752,aaaaaaafzz:0.04488198976629347720):0.09529995111708353117,((aaaaaaadbn:0.34408087090010841536,aaaaaaaafj:0.47991503739434709930):0.06859184769990583908,((aaaaaaaabk:0.09244297511609228524,aaaaaaaete:0.12568841555837687030):0.28431 

(沒有新行)

內像aaaaaaaabk名稱。

其他文件具有信息變化,像這樣在對方的文件,

aaaaaaaabk;Ciona savignyi 
aaaaaaaete;Homo sapiens 
aaaaaaaafj;Cryptosporidium hominis 
aaaaaaaaad;Strongylocentrotus purpuratus 
aaaaaaabyd;Theileria parva 
aaaaaaaaaf;Plasmodium vivax 

我已經試過無數的事情,但是這是我得到的最接近。問題在於它是爲一個而不打印出phylip文件的其餘部分。我需要去((泰勒麥穗魚:0.23400159127856412500等

open(my $tree, "$ARGV[0]") or die "Failed to open file: $!\n"; 
open(my $csv, "$ARGV[0]") or die "Failed to open file: $!\n"; 
open(my $new_tree, "> raxml_tree.phy"); 

# Declare variables 
my $find; 
my $replace; 
my $digest; 

# put the file of the tree into string variable 
my $string = <$tree>; 

# open csv file 
while (my $line = <$csv>) { 

    # aaaaaaaaaa;Ciona savignyi 

    if ($line =~ m/(\w+)\;+(\w+\s+\w*)/) { 
     $find = $1; 
     $replace = $2; 
     $string =~ s/$find/$replace/g; 
    } 
} 
print $new_tree "$string"; 

close $tree; 
close $csv; 
close $new_tree; 

回答

1

在你自己的代碼的一些準則

  • 的問題是幾乎可以肯定,您打開相同的文件$ARGV[0]兩次推測。一個應該是`$ ARGV [1]

  • 必須始終use strictuse warnings一t你寫的每一個Perl程序的頂部(除非有use strict,否則在聲明變量時幾乎沒有什麼意義),並且儘可能地使用my來聲明所有變量,以儘可能接近它們的第一個使用點。在開始時聲明所有變量是不好的形式,因爲它使它們全部有效地全局化,並且失去了聲明詞法變量的大多數優點

  • 您應該使用三參數形式的open ,並且將該文件的名稱放在die字符串中以便您可以查看哪一個失敗是個好主意。所以

    open(my $tree, "$ARGV[0]") or die "Failed to open file: $!\n"; 
    

    成爲

    open my $tree, '<', $ARGV[0] or die qq{Failed to open "$ARGV[0]" for input: $!\n}; 
    
  • 你應該尋找簡單的解決方案,而不是每次都適用的正則表達式的方法。 $line =~ m/(\w+)\;+(\w+\s+\w*)/chomp更爲整潔,split /;/

  • 當你想變的只是值,則不應使用變量左右雙引號,所以print $new_tree "$string"應該print $new_tree $string

而不是試圖用來自其他文件的數據(請嘗試在您的問題中使用有用的名稱作爲項目,因爲在編寫解決方案時很難知道該怎麼稱呼它們),最好構建一個包含所有翻譯的哈希值

這個程序會照你的要求去做。它構建一個由所有散列鍵交替組成的正則表達式,然後將該模式的所有出現轉換爲相應的名稱。只有那些在你的樣品其他文件名翻譯:其他人都離開了,因爲他們是

use strict; 
use warnings; 
use 5.014; # For non-destructive substitution 
use autodie; 

my %names; 
open my $fh, '<', 'other_file.txt'; 
while (<$fh>) { 
    my ($k, $v) = split /;/, s/\s+\z//r; 
    $names{$k} = $v; 
} 

open $fh, '<', 'phylip.txt'; 
my $data = <$fh>; 
close $fh; 

my $re = join '|', sort { length $b <=> length $a } keys %names; 
$re = qr/(?:$re)/; 
$data =~ s/\b($re)\b/$names{$1}/g; 

print $data; 

輸出

((Theileria parva:0.23400159127856412500,(((aaaaaaaaxv:0.44910864993667892753,aaaaaaaagf:0.51328033054009691849):0.06090419044604544752,((aaaaaaabyc:0.11709094683204501752,aaaaaaafzz:0.04488198976629347720):0.09529995111708353117,((aaaaaaadbn:0.34408087090010841536,Cryptosporidium hominis:0.47991503739434709930):0.06859184769990583908,((Ciona savignyi:0.09244297511609228524,Homo sapiens:0.12568841555837687030):0.28431 

更新

這裏是您自己的ab程序的修訂版本ove分數佔據並修正了錯誤

use strict; 
use warnings; 

open my $tree_fh, '<', $ARGV[0] or die qq{Failed to open "$ARGV[0]" for input: $!\n}; 
my $string = <$tree_fh>; 
close $tree_fh; 

open my $csv_fh, '<', $ARGV[1] or die qq{Failed to open "$ARGV[1]" for input: $!\n}; 
while (<$csv_fh>) { 
    chomp; 
    my ($find, $replace) = split /;/; 
    $string =~ s/$find/$replace/g; 
} 
close $csv_fh; 

open my $new_tree_fh, '>', 'raxml_tree.phy' or die qq{Failed to open "raxml_tree.phy" for output: $!\n}; 
print $new_tree_fh $string; 
close $new_tree_fh; 
相關問題