【问题标题】:Partially match to words from two different files and extract rows sed,awk,grep?部分匹配来自两个不同文件的单词并提取行 sed、awk、grep?
【发布时间】:2019-04-19 10:16:16
【问题描述】:

我有两个不同的文件,我想将第一个中的一个数字与另一个数字中的另一个数字部分匹配,然后提取整个列。

文件1:

smt_hsa_3150    932
smt_hsa_28592   682
smt_hsa_5184    657
smt_hsa_430 648
smt_hsa_14100   648
smt_hsa_96 648

文件2:

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 匹配。

【问题讨论】:

标签: awk sed grep


【解决方案1】:

为了好玩,使用 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' *|_' -> 我拆分为多个空格和“_”字符

'{printf "hsa_smt_%06s %s\n", $3, $4}' -> 我将 hsa_smt_ 。如果需要,awk 将添加前导零

sort -k6 file2awk ... | sort -k1 我对第 6 列或第 1 列的文件进行排序

join -11 -26 -o 2.1,2.2,2.3,2.4,2.5,1.1,1.2 我将文件 1 的第一列 (-11) 和文件 2 (-26) 的第 6 列加入文件,然后我对列进行排序 (2.1 -> 文件 2 的第 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,将第三部分转换为整数,以便比较它们。


NR==FNR{split($1,s,"_");smt[s[3]+0]=$2;next} 由于NR==FNR condition,此块将仅在file1 上执行。它拆分第一列,将 smt_hsa id 转换为整数(在 awk 中 +0 是一种将字符串转换为整数的经典方法),然后将第二列存储在名为 smt 的数组中。

next; 阻止执行 file1 的其他块

{split($6,s,"_");k=s[3]+0}这个块将splitfile2的第6列,将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 648

【讨论】:

  • 非常感谢,能不能对awk的每一步做个小解释?
  • 我添加了一些解释,如果您有任何问题,请不要犹豫@K.Gele
  • 我还有一个关于加入两个文件的问题,但它会被标记为重复。我应该如何进行?
  • @KGeles 如果它被设置为重复,那是因为你可以在某个地方得到你的答案?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-23
  • 2020-08-24
  • 2021-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多