我正在尝试对一个太大而无法放入内存的文件进行排序。选项 -m 下的 gnu sort 说明:merge already sorted files; do not sort
. 我正在努力理解这一点的含义,以确保排序完成我想要的。这篇文章(在 Pandas 中对大型数据集进行排序) 建议结合使用 gnu split 和 gnu sort 来完成这样的任务,方法是首先将文件分成适合内存的较小部分,分别对它们进行排序,然后重新组合。到目前为止,我的实验似乎表明这个程序确实有效。尽管如此,我对手册中合并选项的描述感到困扰,该描述说它没有排序。出于我的目的,有必要对大文件进行完全排序,而不仅仅是本地排序的较小部分的串联。虽然我已经在小例子上测试过这个过程并且它似乎有效,但是手册让我对将它应用到我的实际情况缺乏信心,
要给出 MWE,请考虑我要排序的这个制表符分隔文件:
3 4
2 5
3 1
1 3
我尝试了以下操作:
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 选项,则会得到不正确的结果:
## 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 刚刚考虑了两个单独的部分,并根据彼此的第一个值对它们进行了排序。因此,它在这个成品中将第二块放在了第一位,但没有进行其他排序。
或者,如果我遵循此处提倡的程序(在 pandas 中对大型数据集进行排序),即首先对各个部分进行排序然后合并,我似乎确实得到了正确的结果:
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 在使用 merge 选项时会可靠地执行它所声称的操作?手册文本是否以某种方式暗示了此过程无法达到预期结果的某些情况?