如何在awk中基于列的部分字符串匹配连接两个文件
我有两个文件,如下图所示,以制表符分隔: 归档如何在awk中基于列的部分字符串匹配连接两个文件,awk,Awk,我有两个文件,如下图所示,以制表符分隔: 归档 chr1 123,aa aa b c d chr1 234,dd a b c d chr1 af,345,e aa b c d chr1 456 a b c d .... 文件B xxxx abcd chr1 123,dd aa c d e yyyy defg chr1 aa,345 aa e f g ... 我需要根据fileB中的$4和fileA
chr1 123,aa aa b c d
chr1 234,dd a b c d
chr1 af,345,e aa b c d
chr1 456 a b c d
....
文件B
xxxx abcd chr1 123,dd aa c d e
yyyy defg chr1 aa,345 aa e f g
...
我需要根据fileB中的$4和fileA中的$2键连接这两个文件,因此输出如下所示:
chr1 123,aa aa b c d xxxx abcd
chr1 234,dd a b c d xxxx abcd
chr1 af,345,e aa b c d yyyy defg
chr1 456 a b c d
我正在尝试使用解决方案:
awk 'NR==FNR{a[$4]=$1OFS$2;next}{$6=a[$2];print}' OFS='\t' fileb filea
只有当fileA中的$2完全匹配时,这才有效。是否有任何解决方案可以匹配fileA的$2中以逗号分隔的字符串?只需存储fileB中的数据,并在必要时将其连接到fileA中:
awk 'FNR==NR {data[$4]=$1 FS $2; next}
{
split($2,a,",");
if (a[1] in data) {$0=$0 FS data[a[1]]}
}1' fb fa
试验
这假设在fileB中不会出现任何给定的$2文件A中的多个值:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR { fileB[$4] = $1 OFS $2; next }
{
tail = ""
split($2,fileA,/,/)
for (i in fileA) {
if (fileA[i] in fileB) {
tail = OFS fileB[fileA[i]]
}
}
print $0 tail
}
$ awk -f tst.awk fileB fileA
chr1 123,aa aa b c d xxxx abcd
chr1 234,dd a b c d
chr1 af,345,e aa b c d yyyy defg
chr1 456 a b c d
考虑到您的新输入/输出,您将需要类似的内容(未经测试):
另一个
awk
$ awk -v c=',' 'NR==FNR{a[c $4 c]=$1 FS $2; next}
{for(k in a) if(c $2 c~k) $(NF+1)=a[k]}1' fileB fileA |
column -t
chr1 123,aa aa b c d xxxx abcd
chr1 234,dd a b c d
chr1 af,345,e aa b c d yyyy defg
chr1 456 a b c d
这里有很多关于专栏的事情。试着更好地解释这一点。如果fileB中的$4与fileA中$2中用逗号分隔的字符串相匹配,那么将fileB中的$1、$2添加到fileA中的$6中。预期输出中的
chr1 123、aa
来自何处?234可能是234,如果我理解正确,它只匹配[1]元素。可能在示例中,它必须与[1]匹配是正确的。但是,在原始文件中,它可以匹配拆分数组“a”中的任何元素,而不仅仅是a[1]。我不应该回答这个问题,因为很明显,您没有提供足够的详细信息;相反,您会不断在评论中添加更多内容。用a编辑你的原始问题。$(NF+1)
比tail好。这是真的,但它会导致awk重新编译$0,重新评估NF,并重新映射到字段中,因此效率受到影响,NF的结果值将是错误的(echo'a'| awk'{$(NF+1)=“bc print NF}'
将输出2,而echo'a'| awk'{tail=“bc;$0=$0的尾迹;打印NF}“
将输出3。现在,文件B中的$4也有用逗号分隔的字符串,并且不使用多个字符串来匹配文件B。我相信,如果您稍微考虑一下,您可能会发现这是一个结果,而无需实际测试。我编辑了我的答案,以满足新的要求。真的吗如果你什么都不懂的话,你可以试着思考一下你得到的解决方案,并问一些问题,因为在给定特定输入集的情况下,生成你期望的输出的脚本只是确定解决方案的起点,而不是当你使用真实数据wrt output、效率、内存、robus运行它时作为YMMV的终点再次抱歉!!OP更新,刚刚意识到fileB中的$4也有逗号分隔的字符串。这种方法在这种情况下不起作用,但您的示例现在是错误的。fileB的123,dd
应该与fileA中的第1行和第2行匹配。是的!!在这种情况下,它可以添加到fileA中的两行。
BEGIN { FS=OFS="\t" }
NR==FNR {
split($4,b,/,/)
for (i in b) {
fileB[b[i]] = $1 OFS $2
}
next
}
{
tail = ""
split($2,a,/,/)
for (i in a) {
if (a[i] in fileB) {
tail = OFS fileB[a[i]]
}
}
print $0 tail
}
$ awk -v c=',' 'NR==FNR{a[c $4 c]=$1 FS $2; next}
{for(k in a) if(c $2 c~k) $(NF+1)=a[k]}1' fileB fileA |
column -t
chr1 123,aa aa b c d xxxx abcd
chr1 234,dd a b c d
chr1 af,345,e aa b c d yyyy defg
chr1 456 a b c d