Unix联接:在不丢失列顺序的情况下返回不匹配的列



我想使用Unix命令行实用程序(如"join")连接两个文件,这两个文件共享一个已排序的公共标识符列。我希望保留不匹配的行,并保持匹配行和不匹配行之间列顺序的完整性,即使标识符列不在第一行中。

例如,考虑两个文件,1.txt和2.txt:

1.文本:

val1,val2,key
1a,1b,1
2a,2b,2
3a,3b,3

2.txt

key,val3,val4
1,1c,3d
3,3c,3d

然后,我想要的输出是:

key,val1,val2,val3,val4
1,1a,1b,1c,3d
2,2a,2b
3,3a,3b,3c,3d

当限制为匹配行时,像join -t, -1 3 1.txt 2.txt这样的东西可以做我想要的事情:

key,val1,val2,val3,val4
1,1a,1b,1c,3d
3,3a,3b,3c,3d

但它失败了,因为行不匹配(至少在OSX上):join -a 1 -t, -1 3 1.txt 2.txt扭曲了列顺序(注意第2行的键在第3列,而不是第1列):

key,val1,val2,val3,val4
1,1a,1b,1c,3d
2a,2b,2
3,3a,3b,3c,3d

在类似Unix的环境中,实现我想要的结果最简单的方法是什么?

也许这是join中的一个错误(我看不出为什么我所寻找的不是所有情况下的首选行为,但我肯定会错过一些东西)。如果是这样的话,我很乐意帮助解决。。。

我认为您需要指定输出列以获得您想要的结果:

$ join -a 1 -t, -1 3 -o 0,1.1,1.2,2.2,2.3 1.txt 2.txt
key,val1,val2,val3,val4
1,1a,1b,1c,3d
2,2a,2b,,
3,3a,3b,3c,3d
$

-o 0是联接列;其余为CCD_ 6号。请注意,它包括缺失值的空字段(末尾的双,,)。如果这是一个主要问题,您可以明显地删除尾随的(重复的)逗号,而不太明显地删除输出行中间除了一个重复的逗号之外的所有逗号。我会通过sed来提供输出。

在Mac OS X 10.11.4上测试BSD(/usr/bin/join)和GNU(自制——恰好在/opt/gnu/bin/join中)版本的join

首先将2.txt的所有行存储在一个数组中,然后处理1.txt。对于每个找到的行,取1.txt的前2个字段和2.txt的其他字段。

awk -F, 'FNR==NR { from2[$1]=$0; next;}
         {if ($3 in from2) print $1 "," $2 "," from2[$3]; else print $0} ' 2.txt 1.txt

最新更新