我需要用另一个文件中的信息/正则表达式替换一个文件中的变量。例如,我需要从file1中的每一行获取第一个字符串/变量(以MSTRG开头):
MSTRG.5734 MSTRG.5734 509 -4 0 -14 0 0
MSTRG.19266 MSTRG.19266 842 -4 0 -12 0 0
MSTRG.26588 MSTRG.26588 196 5 0 12 0 0
并使用它在file2中搜索看起来像这样的内容:
Chr1 StringTie transcript 24039360 24041181 1000 - . gene_id "MSTRG.5734"; transcript_id "MSTRG.5734.1";
Chr1 StringTie transcript 24039810 24040595 1000 - . gene_id "MSTRG.5734"; transcript_id "Transcript:AT1G64700.1"; ref_gene_id "Gene:AT1G64700"
Chr1 StringTie exon 24040560 24041181 1000 - . gene_id "MSTRG.19266"; transcript_id "MSTRG.19266.1"; exon_number "2";
Chr1 StringTie exon 24040560 24041181 1000 - . gene_id "MSTRG.26588"; transcript_id "MSTRG.26588.1"; exon_number "2";
Chr1 StringTie transcript 24039810 24040595 1000 - . gene_id "MSTRG.26588"; transcript_id "Transcript:AT5G41000.1"; ref_gene_id "Gene:AT5G41000";
理想情况下,例如{2}在file2中的一行中找到,该行也包含字符串,例如MSTRG.5734
,它会获取信息Gene:AT1G64700
并替换file1中的Gene:AT1G64700
。因此,file1中每行的每个MSTRG.5734
都是唯一的,理论上它与file2中的唯一Gene匹配。如果它与Gene不匹配,那么我需要维护file1中的原始行。
File1输出应该如下所示:
MSTRG
我目前的perl代码是:
Gene:AT1G64700 MSTRG.5734 509 -4 0 -14 0 0
MSTRG.19266 MSTRG.19266 842 -4 0 -12 0 0
Gene:AT5G41000 MSTRG.26588 196 5 0 12 0 0
不幸的是,我遇到了困难,不确定如何继续? 感谢上一篇文章给出的任何帮助,赞赏和道歉,我没有为那些看到的人提供任何代码。
答案 0 :(得分:3)
我会这样做:
use 5.014; #needed min 5.014 because the /r modifier
use warnings;
use Path::Tiny '0.077'; #added the min. req. version
my $file1='file1.txt';
my $file2='file2.txt';
my %mstmap = map { split /\s+/, s/.*?gene_id\s*"\s*(MSTRG\.\d+).*ref_gene_id\s*"\s*(Gene:\w+)".*/$1 $2/r }
grep { /ref_gene_id.*Gene:/ } path($file2)->lines({chomp => 1});
path($file1)->edit_lines( sub { s/^(MSTRG\.\d+)/exists($mstmap{$1}) ? $mstmap{$1} : $1/e });
输入文件的生成
Gene:AT1G64700 MSTRG.5734 509 -4 0 -14 0 0
MSTRG.19266 MSTRG.19266 842 -4 0 -12 0 0
Gene:AT5G41000 MSTRG.26588 196 5 0 12 0 0
它为对创建哈希:MSTRG.number
=> Gene:String
(来自file2
),并使用Path::Tiny模块编辑功能执行file1
中的替换。
在@Borodin评论之后,上述内容可以简化为:
use 5.014;
use warnings;
use Path::Tiny '0.077';
my $file1='f1';
my $file2='f2';
my %mstmap = map {
/.*?gene_id\s*"\s*(MSTRG\.\d+).*ref_gene_id\s*"\s*(Gene:\w+).*/
} path($file2)->lines({chomp => 1});
path($file1)->edit_lines( sub { s/^(MSTRG\.\d+)/exists($mstmap{$1}) ? $mstmap{$1} : $1/e });
答案 1 :(得分:2)
没有必要编写坚不可摧的代码来实现您想要的结果
此程序从包含$file2
和%mstrg
字符串的所有行中读取MSTRG.
构建哈希Gene:
。然后它会在$re
中创建一个匹配找到MSTR.
字符串中的任何一个的正则表达式
$file1
被打开,并且该正则表达式用于替换任何散列键以及它在行首处出现的相应散列值。然后打印该行
目前尚不清楚file1.txt
的前两个字段是否始终相同,但我选择仅更改第一个字段
我已经使用autodie
pragma来避免显式检查任何文件IO操作是否成功
程序将输出打印到STDOUT,因此您可以在命令行的任何位置将其重定向
use strict;
use warnings 'all';
use autodie;
my ( $file1, $file2 ) = @ARGV;
my %mstrg;
{
open my $fh, '<', $file2;
while ( <$fh> ) {
$mstrg{$1} = $2 if /"(MSTRG.\d+)".*"(Gene:\w+)"/;
}
}
my $re = join '|', sort { length $b <=> length $a } keys %mstrg;
open my $fh, '<', $file1;
while ( <$fh> ) {
s/^($re)\b/$mstrg{$1}/;
print;
}
Gene:AT1G64700 MSTRG.5734 509 -4 0 -14 0 0
MSTRG.19266 MSTRG.19266 842 -4 0 -12 0 0
Gene:AT5G41000 MSTRG.26588 196 5 0 12 0 0