我有两个大文件(一组文件名)。每个文件大约有3万行。我试图找到一种快速的方法,在file1中查找不存在于file2中的行。

例如,如果这是file1:

line1
line2
line3

这是file2:

line1
line4
line5

那么我的结果/输出应该是:

line2
line3

如此:

Grep -v -f file2 file1

但是在我的大文件上使用时,它非常非常慢。

我怀疑有一个好方法来使用diff(),但输出应该只是行,没有别的,我似乎找不到一个开关。

谁能帮我找到一种快速的方法,使用bash和基本的Linux二进制文件来做到这一点?

编辑:为了跟进我自己的问题,这是我迄今为止发现的使用diff()的最好方法:

 diff file2 file1 | grep '^>' | sed 's/^>\ //'

肯定有更好的办法吧?


当前回答

使用fgrep或在grep中添加-F选项可能会有所帮助。但是为了更快的计算,你可以使用Awk。

您可以尝试以下Awk方法之一:

http://www.linuxquestions.org/questions/programming-9/grep-for-huge-files-826030/#post4066219

其他回答

排序和差分的速度是多少?

sort file1 -u > file1.sorted
sort file2 -u > file2.sorted
diff file1.sorted file2.sorted

你可以使用Python:

python -c '
lines_to_remove = set()
with open("file2", "r") as f:
    for line in f.readlines():
        lines_to_remove.add(line.strip())

with open("f1", "r") as f:
    for line in f.readlines():
        if line.strip() not in lines_to_remove:
            print(line.strip())
'

使用moreutils包中的combine,这是一个集实用程序,不支持和、或、异或操作

combine file1 not file2

也就是说,给我在file1中但不在file2中的行

或者给我file1中的行减去file2中的行

注意:在执行任何操作之前,组合排序并在两个文件中找到唯一的行,而diff则不会。你可能会发现diff和combine的输出不同。

所以实际上你是在说

在file1和file2中找到不同的直线,然后用file1中的直线减去file2中的直线

根据我的经验,这比其他选择要快得多

使用fgrep或在grep中添加-F选项可能会有所帮助。但是为了更快的计算,你可以使用Awk。

您可以尝试以下Awk方法之一:

http://www.linuxquestions.org/questions/programming-9/grep-for-huge-files-826030/#post4066219

就像konsolebox建议的,海报grep解决方案

grep -v -f file2 file1

实际上,如果你简单地添加-F选项,就会工作得更好(更快),将模式视为固定的字符串而不是正则表达式。我在一对~1000行文件列表上验证了这一点,我必须进行比较。当将grep输出重定向到wc -l时,使用-F需要0.031秒(实数),而不使用-F需要2.278秒(实数)。

这些测试还包括-x开关,这是解决方案中必要的一部分,以便在file2包含的行与file1中的一行或多行部分匹配(而不是全部)的情况下确保完全准确。

因此,不需要对输入进行排序,快速,灵活(区分大小写等)的解决方案是:

grep -F -x -v -f file2 file1

这并不适用于所有版本的grep,例如,它在macOS中失败,其中文件1中的一行将显示为不存在于文件2中,即使它匹配的另一行是它的子字符串。或者,您可以在macOS上安装GNU grep以使用此解决方案。