我想使用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