使用其他文件中的信息更改文件

时间:2015-05-23 16:52:07

标签: perl file format alter phylogeny

我想使用其他文件中的信息更改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文件。我需要去((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;

1 个答案:

答案 0 :(得分:1)

关于您自己的代码的一些指南

  • 几乎可以肯定,您要打开两次相同的文件$ARGV[0]。大概应该是`$ ARGV [1]

  • 必须始终 use strictuse warnings位于您编写的每个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

<强>更新

以下是您自己程序的修订版本,其中包含以上几点并修复了错误

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;