我有两个不同的文件,我想将第一个文件中的一个数字与另一个文件中的另一个数字部分匹配,然后提取整个列。
File1:
smt_hsa_3150 932
smt_hsa_28592 682
smt_hsa_5184 657
smt_hsa_430 648
smt_hsa_14100 648
smt_hsa_96 648File2:
chr11 5933549 5933577 29 + hsa_smt_028592
chr11 45693060 45693086 27 - hsa_smt_000059
chr11 45699803 45699832 30 - hsa_smt_000087
chr2 131291172 131291197 26 - hsa_smt_000096我需要将smt_hsa_28592或28592与hsa_smt_028592或028592相匹配。然后将第二个文件中的行加上第一个文件第二列中的数字提取到一个新文件中。
产出:
chr11 5933549 5933577 29 + hsa_smt_028592 682
chr2 131291172 131291197 26 - hsa_smt_000096 648由于我刚开始使用awk/sed编程,我首先尝试将第一个文件的第一列的名称从smt_hsa_3150更改为hsa_smt_3150,但当我执行以下操作时
awk '{gsub("smt","hsa")}1'然后,我不能使用相同的代码只更改第二个"hsa“。第二个问题是如何将hsa_smt_028592与smt_has_28592或smt_hsa_96与hsa_smt_000096相匹配。
发布于 2018-11-16 09:17:27
为了好玩,使用join:
join -11 -26 -o 2.1,2.2,2.3,2.4,2.5,1.1,1.2 <(awk -F' +|_' '{printf "hsa_smt_%06s %s\n", $3, $4}' file1.txt | sort -k1) <(sort -k6 file2.txt)awk命令是将file1的第一列格式化为与file2相同的格式。然后我们加入这两个文件(首先我们需要对它们进行排序)。
awk -F' *|_' -> I在多个空格和"_“字符上拆分
'{printf "hsa_smt_%06s %s\n", $3, $4}' -> i将hsa_smt_<第三列打印为宽度6><4 column>的整数。如果需要,Awk将添加前导零
sort -k6 file2或awk ... | sort -k1我在第6或第1列对文件进行排序
join -11 -26 -o 2.1,2.2,2.3,2.4,2.5,1.1,1.2 I将文件1 (-11)的第一列和文件2 (-26)的第6列连接起来,然后对这些列(2.1 ->,file2第1列等)进行排序.
纯awk解决方案:
awk 'NR==FNR{split($1,s,"_");smt[s[3]+0]=$2;next}{split($6,s,"_");k=s[3]+0}k in smt{print $0, smt[k]}' file1.txt file2.txt在这个解决方案中,我拆分了smt_hsa_xxx和hsa_smt_xxx,将第3部分转换为整数,以便比较它们。
NR==FNR{split($1,s,"_");smt[s[3]+0]=$2;next}这个块将只在file1上执行,因为NR==FNR 条件。它拆分第一列,将smt_hsa id转换为整数(在awk中执行+0是将字符串转换为整数的典型方法),然后将第二列存储在名为smt的数组中。
next;阻止为file1执行其他块
{split($6,s,"_");k=s[3]+0}这个块将拆分第6列的file2,将id转换为整数。我们可以使用“+|_”作为分隔符,以避免拆分列(参见第一个解决方案)。
k in smt{print $0, smt[k]}将检查id是否是smt数组的键。然后从file2和file1的第二列(存储在smt中)打印行。
我确信第二种解决方案更有表现力,但在记忆中可能更贪婪。
两者输出相同,行的顺序可能不同:
chr11 5933549 5933577 29 + hsa_smt_028592 682
chr2 131291172 131291197 26 - hsa_smt_000096 648https://stackoverflow.com/questions/53334229
复制相似问题