![根据公共的两列连接两个表,如果不匹配则添加 NA 或空值](https://linux22.com/image/194799/%E6%A0%B9%E6%8D%AE%E5%85%AC%E5%85%B1%E7%9A%84%E4%B8%A4%E5%88%97%E8%BF%9E%E6%8E%A5%E4%B8%A4%E4%B8%AA%E8%A1%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%8C%B9%E9%85%8D%E5%88%99%E6%B7%BB%E5%8A%A0%20NA%20%E6%88%96%E7%A9%BA%E5%80%BC.png)
我想像这样合并两个表
表格1
Chr1 5
Chr1 10
Chr1 20
Chr2 10
Chr2 30
表_2
Chr1 10 value value2
Chr1 20 value value2
Chr2 30 value value2
所需输出
Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2
我在 awk 中找到了用于合并表的脚本,仅保留与两个表中的两列匹配的行。但在这里,我想要 Table_1 的所有行,但如果它们匹配,则添加 Table_2 的值。您能告诉我如何实现这一目标吗?
答案1
$ awk '{ key = $1 FS $2 };
NR == FNR { t[key] = $0; next };
key in t { print t[key]; next };
1' table2.txt table1.txt
Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2
在读取的每个输入行(对于读取的两个文件)中,变量
key
设置为前两个字段($1
和$2
),并在它们之间使用字段分隔符(FS
)。FS
使用它是因为它是唯一保证不在任一字段中的字符),因此也是唯一保证生成唯一键的字符。该键用作名为 的关联数组的索引t
。当它读到时
table2.txt
时(必须被列为命令行上的第一个文件名 arg),每个输入行都存储在数组的一个元素中t
。如果
table2.txt
包含重复的条目 - 即具有相同前两个字段的多行 - 它只会记住最后的一个看到的。如果您希望它记住所有此类重复项(按照出现的顺序),请将 awk 脚本的第二行更改为:NR == FNR { if (key in t) { t[key] = t[key] "\n" $0 } else { t[key] = $0 }; next };
当它完成读取第一个文件时,它读入
table1.txt
(第二个文件名arg)并打印数组中的相应条目table2
(如果存在),否则打印当前行。1
脚本最后一行的是awk
awk 的惯用简写形式{print}
- 值1
计算为 true,当某些值计算为 true 时,默认操作是打印当前行。
注意:如果table2.txt
很大,这将使用大量 RAM。对于任何具有千兆字节 RAM 的现代系统来说,这不太可能成为问题。
答案2
$ awk '{k=$1 FS $2} NR==FNR{map[k]=$0; next} {print (k in map ? map[k] : $0)}' table2 table1
Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2