根据可能不完整的键合并文件

sad*_*ddd 5 text-processing merge paste

我想合并两个文件,例如如何根据两列的匹配合并两个文件?但一个文件可能无法包含所有结果。例如

文件1

1 dog
2 cat
3 fox
4 cow
Run Code Online (Sandbox Code Playgroud)

文件2

1 woof
2 meow
4 mooh
Run Code Online (Sandbox Code Playgroud)

想要的输出

1 dog woof
2 cat meow
3 fox
4 cow mooh
Run Code Online (Sandbox Code Playgroud)

Ed *_*ton 6

使用 GNU awk 处理数组的数组:

$ awk '{a[$1][(NR>FNR)]=$2} END{for (i in a) print i, a[i][0], a[i][1]}' file{1,2}
1 dog woof
2 cat meow
3 fox
4 cow mooh
Run Code Online (Sandbox Code Playgroud)

或使用任何 awk:

$ awk '{keys[$1]; a[$1,(NR>FNR)]=$2} END{for (i in keys) print i, a[i,0], a[i,1]}' file{1,2}
1 dog woof
2 cat meow
3 fox
4 cow mooh
Run Code Online (Sandbox Code Playgroud)

尽管上面的输出按第一个字段的数字升序排列,但这只是运气/巧合 - 输出行的顺序实际上是由“in”运算符提供的“随机”(通常是哈希顺序)。如果您关心的话,将输出通过管道传输到sort -k1,1n(或PROCINFO["sorted_in"]="@ind_num_asc"在 GNU awk 中的 END 部分的开头设置)。

该解决方案与解决方案之间的显着区别join在于:

  1. 即使输入未排序,而join需要在关键字段上对输入进行排序,这也将起作用,并且,
  2. 如果 file2 中有一行的键不存在于 file1 中(反之亦然),这将以某种方式显示它,以便您可以知道该唯一行来自哪个文件(与添加到命令不同-a2join

这里有一些更全面的示例输入/输出用于测试:

$ head file{1,2}
==> file1 <==
1 dog
2 cat
4 cow
5 bear

==> file2 <==
1 woof
2 meow
3 growl
4 mooh
Run Code Online (Sandbox Code Playgroud)

然后我们可以运行上面的 awk 脚本来获得相同的输出:

$ awk '{a[$1][(NR>FNR)]=$2} END{for (i in a) print i, a[i][0], a[i][1]}' file{1,2}
1 dog woof
2 cat meow
3  growl
4 cow mooh
5 bear
Run Code Online (Sandbox Code Playgroud)

并注意3 growl前面有一个额外的空白growl,因此您知道这是 file2 中的唯一行,而不是使用join

$ join -a1 -a2 file1 file2
1 dog woof
2 cat meow
3 growl
4 cow mooh
5 bear
Run Code Online (Sandbox Code Playgroud)

您无法区分 file1 中的唯一行(例如5 bear)和 file2 中的唯一行(例如3 growl)。


avi*_*iro 5

假设 file1 和 file2 都已排序,join默认情况下只会连接两个文件都有其密钥的行。因此,在您的情况下,file2 没有键为“3”的行,因此该行未加入。但是,您可以更改此行为。

在以下的手册页中join

   -a FILENUM
          also print unpairable lines from file FILENUM, where FILENUM is 1 or 2, corresponding to FILE1 or FILE2
Run Code Online (Sandbox Code Playgroud)

因此,如果您将-a1标志添加到join命令中,则 file1 中任何在 file2 中没有匹配键的行也将被打印。

# join -a1 file1 file2
1 dog woof
2 cat meow
3 fox
4 cow mooh
Run Code Online (Sandbox Code Playgroud)

请注意,这不会处理 file2 中不可配对的行,因此如果在 file2 中您还有另一行,例如:

5 quack
Run Code Online (Sandbox Code Playgroud)

该行不会被打印。您还可以在命令中添加-a2标志join,该标志将打印 file2 中的行,但这只会增加一些混乱,因为您不知道该行是来自 file1 还是来自 file2。