【问题标题】:Best way to print rows not common to two large files in Unix打印Unix中两个大文件不常见的行的最佳方法
【发布时间】:2013-01-03 09:08:08
【问题描述】:

我有两个格式如下的文件。
File1: - 它包含 4 列。第一个字段是文本格式的 ID,其余列也是一些文本值。

id1 val12 val13 val14
id2 val22 val23 val24
id3 val32 val33 val34

File2 - 在文件 2 中我只有 ID。

id1
id2

输出

id3 val32 val33 val34

我的问题是:如何从第一个文件中查找 ID(第一个字段)未出现在第二个文件中的行。这两个文件的大小都非常大,file1 包含 4200 万行,大小为 8GB,file2 包含 3300 万个 ID。两个文件中的 ID 顺序可能不同。

【问题讨论】:

  • 有了这么多数据,您很可能会获得更好的性能,将其填充到数据库中并编写 SQL。
  • 好吧,我更喜欢 join。但你也可以使用 awk:theunixshell.blogspot.com/2012/12/…

标签: linux unix awk


【解决方案1】:

假设这两个文件是按id排序的,那么类似

join "-t " -j 1 -v 1 file1 file2

应该这样做。

【讨论】:

  • +1 不错。你不需要-t" "-j1,这些是默认值。
  • 谢谢,我不记得 -t 的默认值了。
  • 文件未排序。我曾经尝试在其上对 file1 进行排序,但这需要很长时间。 ID的长度真的很大。它的 md5sum 长度约为 150 个字符。
  • 在这种情况下,我会考虑 Thor 的解决方案(只是因为我认为 RAM 使用率会更低)。请记住,其他解决方案会将 file2 加载到 RAM 中。我认为 150*33000000 大约是 5GB。最好有一台像样的机器。
  • @Jitendra:可以使用-m 开关分阶段进行排序并并行化,例如参见this GNU 并行示例。
【解决方案2】:

你可以用 awk 做这样的事情:

awk 'FNR == NR { h[$1] = 1; next } !h[$1]' file2 file1

第一个块将来自 file2 的 id 收集到 h 哈希中。如果 file2 中不存在 id,最后一部分 (!h[$1]) 将执行默认块 ({ print $0 })。

【讨论】:

  • 请注意,这需要将整个 File2 保存在内存中。
  • @glennjackman:确实如此,file1file2 未排序的任何解决方案都是这种情况。
【解决方案3】:

我并不是说这是“最好”的方法,因为最好可以包含许多权衡标准,但这里有一种方法:

您可以使用-f 选项将File2 指定为包含grep 的搜索模式的文件:

grep -v -f File2 File1 > output

正如@glennjackman 建议的那样:

强制 id 在行首匹配的一种方法:grep -vf <(sed 's/^/^/' File2) File1

【讨论】:

  • 这可能会失败,当来自File2 的一些 id 作为值出现在File1 中时。
  • 情况并非如此。 ID 不会显示为值。
  • 他需要 -v 选项,因为他不希望 File1 中 File2 的行
  • 强制 id 在行首匹配的一种方法:grep -vf <(sed 's/^/^/' File2) File1
  • @glennjackman 谢谢!我想了想,想不出一个优雅的方式来做这件事——这太完美了
猜你喜欢
  • 2014-09-02
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 2017-01-14
  • 2018-01-10
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多