根据每行的第一个标记比较两个大文件的最佳方法是什么?

2024-10-01 09:29:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个大文件(每个大约500k行或85mb)包含文件和文件路径本身的校验和。基于校验和获得文件之间差异的最佳方法是什么?我可以编写Java程序、脚本等,但目标是它必须高效。你知道吗

例如,我有文件a:

ec7a063d3990cf7d8481952ffb45f1d8b490b1b5  /home/user/first.txt
e0f886f2124804b87a81defdc38ad2b492458f34  /home/user/second.txt

文件B:

650bc1eb1b24604819eb342f2ebc1bab464d9210  /home/user/third.txt
ec7a063d3990cf7d8481952ffb45f1d8b490b1b5  /home/user/blah/dup.txt

我想输出两个包含文件A和B中唯一文件的文件

唯一

e0f886f2124804b87a81defdc38ad2b492458f34  /home/user/second.txt

独一无二的

650bc1eb1b24604819eb342f2ebc1bab464d9210  /home/user/third.txt

在这种情况下第一.txt“和”dup.txt文件“是相同的,因为它们的校验和是相同的,所以我排除它,因为它不是唯一的。最有效的方法是什么?文件没有按任何方式排序。你知道吗


Tags: 文件方法路径程序txthome差异java
3条回答

使用sort对每个文件进行排序,然后将结果与comm进行比较。这两个命令的用法在namesake手册页面中有说明。你知道吗

只有bash的解决方案:

# create a file with a mark that help to find the source of the hash remove duplicate 
sed 's/^\([0-9a-f]*\)[^0-9a-f]/\1=A=/' FileA | sort | uniq -w 32 > FileA.mark
sed 's/^\([0-9a-f]*\)[^0-9a-f]/\1=B=/' FileB | sort | uniq -w 32 > FileB.mark

# sort the 2 files together , keep only unique hashs 
sort -t= FileA.mark FileB.mark | uniq -w 32 -c  >  HashCountFromAB

# if the count equal 1 ( provide by option -c from uniq )
# we use the mark to find the origin of the hash 

grep '^ *1 [0-9a-f]*=A=' HashCountFromAB > FileA.uniq
grep '^ *1 [0-9a-f]*=B=' HashCountFromAB > FileB.uniq

所以这里有一个简单的答案,但效率不高:

$ join -v1 <(sort FileA) <(sort FileB) | tee UniqueA
e0f886f2124804b87a81defdc38ad2b492458f34 /home/user/second.txt

$ join -v2 <(sort FileA) <(sort FileB) | tee UniqueB
650bc1eb1b24604819eb342f2ebc1bab464d9210 /home/user/third.txt

join命令按键匹配两个已排序文件中的行(默认情况下,这是第一个具有默认分隔符的字段)。不过,上面的命令并不是很有效,因为我们对文件进行了两次排序:一次是获取第一个文件(-v1)的唯一值,另一次是获取第二个文件(-v2)的唯一值。我很快就会发布一些改进。你知道吗

您可以在一次调用中获得唯一的值,但原始文件将丢失。请参见下面的代码:

$ join -v1 -v2 <(sort FileA) <(sort FileB)
650bc1eb1b24604819eb342f2ebc1bab464d9210 /home/user/third.txt
e0f886f2124804b87a81defdc38ad2b492458f34 /home/user/second.txt

在这一点上,我们几乎得到了答案。我们有两个文件中所有不匹配的文件。而且,我们只对每个文件进行了一次排序。我相信这是有效的。但是,您丢失了“来源”信息。我们可以使用以下迭代或代码用sed标记行:

$ join -v1 -v2 <(sort FileA | sed s/$/\ A/ ) <(sort FileB | sed s/$/\ B/ )
650bc1eb1b24604819eb342f2ebc1bab464d9210 /home/user/third.txt B
e0f886f2124804b87a81defdc38ad2b492458f34 /home/user/second.txt A

在这一点上,我们有我们独特的条目,我们知道他们来自的文件。如果您必须将结果放在单独的文件中,我认为您可以使用awk(或更多bash)来完成这一点。下面是包含awk的代码的又一次迭代:

join -v1 -v2 <(sort FileA | sed s/$/\ A/ ) <(sort FileB | sed s/$/\ B/ ) |  awk '{ file="Unique" $3 ; print $1,$2 > file }

相关问题 更多 >