我是Perl的新手,我担心自己陷入困境,想知道是否有人可以帮助我。
我有一个包含oldname和newname的两列(制表符分隔)的文件。
我想将oldname用作key和newname作为值,并将其存储为哈希值。
然后我想打开一个不同的文件(gff文件)并用新名称替换其中的所有旧名称并将其写入另一个文件。
我已尽力尝试,但却遇到了很多错误。
如果你能让我知道我做错了什么,我将不胜感激。
以下是两个文件的外观:
oldname newname(SFXXXX)文件:
genemark-scaffold00013-abinit-gene-0.18 SF130001
augustus-scaffold00013-abinit-gene-1.24 SF130002
genemark-scaffold00013-abinit-gene-1.65 SF130003
要搜索和替换的文件(其中一行的示例):
scaffold00013 maker gene 258253 258759 . - . ID=maker-scaffold00013-augustus-gene-2.187;Name=maker-scaffold00013-augustus-gene-2.187;
这是我的尝试:
#!/usr/local/bin/perl
use warnings;
use strict;
my $hashfile = $ARGV[0];
my $gfffile = $ARGV[1];
my %names;
my $oldname;
my $newname;
if (!defined $hashfile) {
die "Usage: $0 hash_file gff_file\n";
}
if (!defined $gfffile) {
die "Usage: $0 hash_file gff_file\n";
}
###save hashfile with two columns, oldname and newname, into a hash with oldname as key and newname as value.
open(HFILE, $hashfile) or die "Cannot open $hashfile\n";
while (my $line = <HFILE>) {
chomp($line);
my ($oldname, $newname) = split /\t/;
$names{$oldname} = $newname;
}
close HFILE;
###open gff file and replace all oldnames with newnames from %names.
open(GFILE, $gfffile) or die "Cannot open $gfffile\n";
while (my $line2 = <GFILE>) {
chomp($line2);
eval "$line2 =~ s/$oldname/$names{oldname}/g";
open(OUT, ">SFrenamed.gff") or die "Cannot open SFrenamed.gff: $!";
print OUT "$line2\n";
close OUT;
}
close GFILE;
谢谢!
答案 0 :(得分:3)
您的主要问题是您没有拆分$line
变量。 <{1}}默认情况下会split /\t/
拆分,而您还没有放任何东西。
该程序构建哈希,然后通过按长度的降序对它们进行排序并使用$_
正则表达式交替运算符将它们连接起来,从所有键构造正则表达式。排序是必要的,以便在有任何替代选择的情况下选择所有可能选择的最长。
每次出现的正则表达式都会被输入文件每行中相应的新名称替换,并且输出会写入新文件。
|
答案 1 :(得分:2)
你为什么使用评估?并且$oldname
将在第二个while循环中未定义,因为您在该范围内重新声明它们的第一个while循环(即使您使用了外部范围,它也会存储您处理的最后一个值,这将不会没有用。)
取出脚本顶部的my $oldname
和my $newname
,这是没用的。
取出整个eva
l行。您需要为要替换的每个事物重复正则表达式。尝试类似:
$line2 =~ s/$_/$names{$_}/g for keys %names;
另见鲍罗丁的回答。他做了一个大的正则表达式而不是一个循环,并且发现你缺乏第二个分裂的论点。