我想合并两个文件并加上两个文件的第二列。
文件1。
001 A
002 B
003 C
004 D
文件2。
002 D
003 D
005 E
006 F
应合并到文件 3 中,如下所示。
001 A
002 B D
003 C D
004 D
005 E
006 F
我尝试了这个命令,由 andreatsh 在这里建议:使用 AWK 合并两个文件并加上第二列:
$ awk '{ z[$1]=z[$1]$2 } END { for (i in z) print i, z[i] }' file1 file2
002 BD
003 CD
004 D
ETC...
这非常接近,但是我如何在字母之间添加空格呢?
例如,第一行中不要使用“BD”,而应使用“B D”
答案1
是的,你可以使用 Awk 来完成,但 Join 就是为了这个任务而生的:
join -a1 -a2 file1 file2
给定样本的输出:
001 A
002 B D
003 C D
004 D
005 E
006 F
注意运行前需要对文件进行排序join
。如果您的 shell 支持,您可以使用以下命令一步完成流程替代:
join -a1 -a2 <(sort file1) <(sort file2)
答案2
正确的工具确实是join
,正如卡西莫多向你展示的那样,但您也可以使用相同的 awk 命令,只需进行很小的修改:
$ awk '{ z[$1]=z[$1]" "$2 } END { for (i in z) print i, z[i] }' file1 file2
002 B D
003 C D
004 D
005 E
006 F
001 A
我只是z[$1]=z[$1]$2
改为z[$1]=z[$1]" "$2
.
答案3
我添加004 D
到 file2 所以我们有一个不明显的案例来测试。鉴于此,要么这样:
$ sort -k1,1 -s file1 file2 |
awk '
$1 != prev { if (NR>1) print ""; printf "%s", $1; prev=$1 }
{ printf " %s", $2 }
END { print "" }
'
001 A
002 B D
003 C D
004 D D
005 E
006 F
或这个:
$ sort -k1,1 -s file1 file2 |
awk '
$1 != prev{if (NR>1) print ""; printf "%s", $1; prev=$1; delete seen }
!seen[$2]++ { printf " %s", $2 }
END { print "" }
'
001 A
002 B D
003 C D
004 D
005 E
006 F
取决于您希望如何处理同一键的重复值。只要列出任意数量的文件就行了sort
。上面假设 GNU sort for-s
保留相同键的输入顺序,如果您没有它并且实际上需要它,则有简单的替代方案。如果您愿意,您还可以进行简单的调整,以便始终让 ABC 等在每个输出行上按字母顺序排列,而不是按它们在每个输入文件中出现的顺序排列,例如:
$ head file*
==> file1 <==
001 A
002 E
003 F
004 D
==> file2 <==
002 D
003 D
004 D
005 E
006 F
==> file3 <==
001 A
002 E
003 C
004 D
$ sort -s file* | awk '$1 != prev{if (NR>1) print ""; prev=$1; delete seen; printf "%s", $1} !seen[$2]++{printf " %s", $2} END{print ""}'
001 A
002 D E
003 C D F
004 D
005 E
006 F