在不同的文件中设置元素的并集

时间:2014-09-15 17:03:04

标签: shell file-io bigdata

我有多个这样的文件:

file1:

item1
item2
item3

file2:

item1
item5
item3

file3:

item2
item1
item4

我想要一个包含所有独特元素的文件。我可以用Python做到这一点,唯一的问题是每个文件包含不同的百万行,我想知道是否有更好的方法(可能只使用shell脚本?)。

2 个答案:

答案 0 :(得分:4)

怎么样:

cat * | uniq

如果每个文件本身包含重复,则可能会提高效率:

for file in *; do cat $file | uniq; done | uniq

如果它们不是排序文件,uniq不起作用,所以这可能不会更有效,因为您需要:

for file in *; do sort $file | uniq; done | sort | uniq

答案 1 :(得分:2)

如果您想要所有三个文件之间的共同元素,另一种方法是使用一些grep操作:

$ grep -F -f file1 file2 > file1inFile2
$ grep -F -f file1 file3 > file1inFile3
$ grep -F -f file1inFile2 file1inFile3 > elementsInCommon

-f选项指定搜索模式文件(在这种情况下为file1file1inFile2)。 -F选项执行固定字符串搜索。

如果你使用bash,你可以做一个花哨的单行:

$ grep -F -f <(grep -F -f file1 file2) <(grep -F -f file1 file3) > elementsInCommon
我认为,Grep在次线性时间搜索。因此,这可能会解决使用sort|uniq方法预分析非常大的文件的常规 O(n log n)时间成本。

您可以进一步加快固定字符串grep操作,specifying LC_ALL=C环境变量。但是,当我探索这个时,它似乎是一个shell默认值。尽管如此,考虑到报告的时间改进,如果您使用grep,此设置似乎值得研究。

但是,Grep可能会使用相当数量的内存加载模式,考虑到输入文件的大小,这可能是一个问题。您可以使用三个文件中最小的一个作为模式源。

但是,如果输入已经排序,则可以一次一行地遍历每个文件,测试三行之间的字符串相等性。然后,您可以将一些输入文件指针向前移动一行,或者打印三个输入共有的相等字符串。这种方法使用 O(n)时间(你遍历每个文件一次)和 O(1)内存(缓冲三行)。更多的时间,但更少的记忆。不确定是否可以使用bash内置函数或核心实用程序来完成,但这绝对可以用于Python,Perl,C等。