基于第二个文件中的模式匹配映射第一个文件的字段

基于第二个文件中的模式匹配映射第一个文件的字段

我有两个制表符分隔的文件,我需要将文件 1 第一列中的文本与任何文件 2 的行中的位置。匹配后,我想将文件 1 的匹配行的第二列中的内容打印到文件 2 中的匹配行的末尾(下面的示例)。

我知道这几乎可以肯定可以用 awk 完成,但我不太擅长使用 awk 或 sed,并且在这里搜索相关问题并尝试调整他们的脚本对我来说没有成功。任何意见将不胜感激。

文件1

protein_1.p1     note "PJD5F7, match to databaseID=64575, (species X)";
protein_1.p2     note "PJD5F7, match to databaseID=64575, (species X)";
protein_3.p1     note "PA5F9H, match to databaseID=93689, (species W)";
protein_4.p1     note "Q7GT5J, match to databaseID=89045, (species Y)";
protein_4.p3     note "YE6G3L, match to databaseID=44968, (species Z)";

文件2

chromosome_1    programID   transcript_id "protein_1.p1"; parent "protein_1";
chromosome_1    programID   transcript_id "protein_1.p2"; parent "protein_1";
chromosome_1    programID   transcript_id "protein_2.p1"; parent "protein_2";
chromosome_1    programID   transcript_id "protein_2.p2"; parent "protein_2";
chromosome_1    programID   transcript_id "protein_3.p1"; parent "protein_3";
chromosome_1    programID   transcript_id "protein_4.p1"; parent "protein_4";
chromosome_1    programID   transcript_id "protein_4.p2"; parent "protein_4";
chromosome_1    programID   transcript_id "protein_4.p3"; parent "protein_4";

所需输出

chromosome_1    programID   transcript_id "protein_1.p1"; parent "protein_1"; note "PJD5F7, match to databaseID=64575, (species X)";
chromosome_1    programID   transcript_id "protein_1.p2"; parent "protein_1"; note "PJD5F7, match to databaseID=64575, (species X)";
chromosome_1    programID   transcript_id "protein_2.p1"; parent "protein_2";
chromosome_1    programID   transcript_id "protein_2.p2"; parent "protein_2";
chromosome_1    programID   transcript_id "protein_3.p1"; parent "protein_3"; note "PA5F9H, match to databaseID=93689, (species W)";
chromosome_1    programID   transcript_id "protein_4.p1"; parent "protein_4"; note "Q7GT5J, match to databaseID=89045, (species Y)";
chromosome_1    programID   transcript_id "protein_4.p2"; parent "protein_4";
chromosome_1    programID   transcript_id "protein_4.p3"; parent "protein_4"; note "YE6G3L, match to databaseID=44968, (species Z)";

答案1

我们可以解析file1,将值($2)映射到键($1),然后file2当行()的一部分与$3任何键匹配时解析并将值附加到行。

BEGIN {OFS = FS = "\t"}
FNR == NR {arr[$1] = $2; next}
{for (x in arr) if ($3 ~ x) {$0 = $0 " " arr[x]; break}}
{print}

这会为您的示例打印正确的结果,但由于多种原因,这不是您想要的。第一个是它可能会在各种情况下失败,例如protein_1.p1protein_1.p11。第二个原因是性能,file2 的每一行的时间不是恒定的,而是 ~ 的大小file1


所以我们要修改上面的脚本。您可能想要定义一个正则表达式来匹配蛋白质字符串。这样,匹配就变得足够严格,并且在第二次解析时,时间取决于在字段上匹配正则表达式,而不是数组大小。

BEGIN {OFS = FS = "\t"; re = "\\<protein_[[:digit:]]+.p[[:digit:]]+\\>"}
FNR == NR {if ($1 ~ re) arr[$1] = $2; next}
match($3, re) {$0 = $0 " " arr[substr($3,RSTART,RLENGTH)]}
{print}

笔记:

  • re:“蛋白质_”后跟一位或多位数字,“.p”,然后再一位或多位数字所有这些内部单词边界。点是字面意思。单词字符是[:alnum:]_所以其余的都是边界。
  • 此外,还对 的第一个字段进行健全性检查file1
  • 如果match()找到 a,则内置变量RSTART保存RLENGTH匹配字符串的索引和长度,这个子字符串就是我们用于哈希的内容。

用法:

> awk -f tst.awk file1 file2
chromosome_1    programID   transcript_id "protein_1.p1"; parent "protein_1"; note "PJD5F7, match to databaseID=64575, (species X)";
chromosome_1    programID   transcript_id "protein_1.p2"; parent "protein_1"; note "PJD5F7, match to databaseID=64575, (species X)";
chromosome_1    programID   transcript_id "protein_2.p1"; parent "protein_2"; 
chromosome_1    programID   transcript_id "protein_2.p2"; parent "protein_2"; 
chromosome_1    programID   transcript_id "protein_3.p1"; parent "protein_3"; note "PA5F9H, match to databaseID=93689, (species W)";
chromosome_1    programID   transcript_id "protein_4.p1"; parent "protein_4"; note "Q7GT5J, match to databaseID=89045, (species Y)";
chromosome_1    programID   transcript_id "protein_4.p2"; parent "protein_4"; 
chromosome_1    programID   transcript_id "protein_4.p3"; parent "protein_4"; note "YE6G3L, match to databaseID=44968, (species Z)";

相关内容