我有两个大文件(一组文件名)。每个文件大约有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/^>\ //'

肯定有更好的办法吧?


当前回答

comm命令(common的缩写)可能很有用,可以逐行比较两个排序好的文件

#find lines only in file1
comm -23 file1 file2 

#find lines only in file2
comm -13 file1 file2 

#find lines common to both files
comm -12 file1 file2 

man文件实际上是相当可读的。

其他回答

你可以使用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())
'

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

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

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

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

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

我通常使用——suppress-common-lines标志来做到这一点,但请注意,这只在您以并排格式执行时才有效。

Diff -y——suppress-common-lines file1.txt file2.txt

如果你缺少“花哨的工具”,例如在一些最小的Linux发行版中,有一个解决方案,只需cat, sort和uniq:

cat includes.txt excludes.txt excludes.txt | sort | uniq --unique

测试:

seq 1 1 7 | sort --random-sort > includes.txt
seq 3 1 9 | sort --random-sort > excludes.txt
cat includes.txt excludes.txt excludes.txt | sort | uniq --unique

# Output:
1
2    

与grep相比,这也相对较快。