gnu-sort - what does manual mean when it says merge option does “not sort”
我试图对一个太大而无法放入内存的文件进行排序。选项-m下的gnu排序的人声明:
要提供MWE,请考虑我要排序的此选项卡分隔文件:
1 2 3 4 | 3 4 2 5 3 1 1 3 |
我尝试了以下操作:
1 2 3 4 5 6 7 8 | SortDir="/Users/aireties/Desktop/Sort_Experiments" ## sort document as a whole (in practice, this would be infeasible due to document size) sort --field-separator=$'\t' -k 1,1 -k 2,2"$SortDir/To_Be_Sorted.txt" -o"$SortDir/Sorted_as_Whole.txt" ## sort first by the first column values, then by the second 1 3 2 5 3 1 3 4 |
这是在立即对整个文件进行排序时的"正确"解决方案(在我的实际用例中这是不可行的)。
如果我试图将文件分成几块然后立即使用-m选项,我得到一个不正确的结果:
1 2 3 4 5 6 7 8 9 10 11 | ## Break file into pieces MaxLines=2 mkdir"$SortDir/Pieces/" split -l $MaxLines"$SortDir/To_Be_Sorted.txt""$SortDir/Pieces/" ## Try merge sort on pieces without first sorting them sort -m --field-separator=$'\t' -k 1,1 -k 2,2"$SortDir/Pieces/"* -o"$SortDir/Sorted_in_Pieces1.txt" 3 1 1 3 3 4 2 5 |
它出现的情况是,gnu sort只考虑了两个单独的部分,并根据彼此的第一个值对它们进行了排序。因此,它已将第二件放在这件成品中,但没有进行其他分类。
或者,如果我按照这里提倡的程序(在大熊猫中为大型数据集排序),即首先对各个部分进行排序然后合并,我似乎得到了正确的结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | for file in"$SortDir/Pieces/"* ## sorts all text files in pwd do sort --field-separator=$'\t' -k 1,1 -k 2,2"$file" -o"$file" done sort -m --field-separator=$'\t' -k 1,1 -k 2,2"$SortDir/Pieces/"* -o"$SortDir/Sorted_in_Pieces2.txt" 1 3 2 5 3 1 3 4 cmp --silent"$SortDir/Sorted_in_Pieces1.txt""$SortDir/Sorted_as_Whole.txt" || echo"files are different" # file are different cmp --silent"$SortDir/Sorted_in_Pieces2.txt""$SortDir/Sorted_as_Whole.txt" || echo"files are different" |
对我来说,关键点在于,如果片段文件很大,那么仍然需要进行大量计算才能将它们合并到一个正确排序的单个文件中。因此,我发现我很难理解如何将这种非平凡的排序描述为声称它"不排序"的操作的结果。
任何人都可以告诉我为什么手册会被这样说?为什么以及如何确信gnu sort在使用合并选项时能够可靠地执行它所声称的内容?手册文本是否暗示某些情况下该程序无法达到预期效果?
Gnu排序(至少是我查看源代码的版本),将对内存中的文件块进行排序,并创建一组临时文件(每个块一个临时文件)。它还在内存排序阶段使用多线程(命令行参数可以设置要使用的最大线程数)。在创建所有临时文件之后,它会对临时文件执行16路合并(除非您覆盖它),直到它生成单个排序文件。
这里的要点是您不必先将文件拆分为单独的文件,因为gnu sort会自动处理大文件,根据需要创建排序的临时文件以合并到单个排序文件中。
-m选项适用于要合并多个已排序文件的特殊情况。
因此,为了对非常大的文件进行排序,您所做的工作确实有效:将其拆分为几个较小的文件,在本地对它们进行排序。此时,如果你只是将每个文件追加到另一个文件,你最终会得到像
例如,那些:
1 2 3 4 5 6 7 8 9 10 11 12 13 | a b 1 3 2 2 3 1 sort -m a b # 1 2 3 3 2 1 sort -m a a # 1 1 2 2 3 3 sort -m b b # 3 2 1 3 2 1 sort -r -m b a # 3 2 1 1 2 3 |