0

別のファイルの情報を使用して、phylip ファイルの名前を変更したいと考えています。phylip は情報の連続した 1 つの文字列にすぎず、変更したい名前 (例: 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

いろいろ試しましたが、これが一番近いです。問題は、それが 1 つだけ実行され、残りの phylip ファイルが出力されないことです。((Theileria parva: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;
4

1 に答える 1

1

独自のコードに関するガイドライン

  • 問題はほぼ確実に、同じファイル$ARGV[0]を 2 回開いていることです。おそらく 1 つは `$ARGV[1] であるべきです

  • 作成するすべての Perl プログラムの先頭で常に (適切な場所にない限り、変数を宣言する意味はほとんどありません)、すべての変数を最初の使用ポイントにできるだけ近い場所で宣言する必要があります。最初にすべての変数をブロックで宣言するのは悪い形式です。なぜなら、それらがすべて効果的にグローバルになり、レキシカル変数を宣言する利点のほとんどが失われるからです。use strictuse warningsuse strictmy

  • の 3 つのパラメーター形式を使用する必要があります。どのファイルが失敗したかがわかるよう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*)/のようにずっときれいですchompsplit /;/

  • 変数の値だけが必要な場合は、変数を二重引用符で囲む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

アップデート

上記の点を考慮し、バグを修正した、独自のプログラムの改訂版を次に示します。

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;
于 2015-05-23T17:12:12.087 に答える