我正在尝试对文件进行排序,该文件太大而无法放入内存中。选项-m下的gnu排序的人声明:merge already sorted files; do not sort
。我正在努力理解这一点的含义,以确保排序完成我想要的。这篇文章(Sorting in pandas for large datasets)建议将gnu split和gnu sort组合起来完成这样的任务,首先将文件分成适合内存的小块,分别对每个文件进行排序,然后重新组合。到目前为止,我的实验似乎表明这个程序确实有效。尽管如此,我对手册中合并选项的描述感到困扰,该选项表明它没有排序。出于我的目的,有必要对大文件进行完全排序,而不仅仅是已经本地排序的较小片段的串联。虽然我已经在小例子上测试过程并且似乎有效,但是手册让我对将其应用到我的实际情况缺乏信心,因为我担心在不再可行验证gnu的情况下是否会出现意外行为排序按我的意图运作。
要提供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刚刚考虑了两个独立的部分,并根据彼此的第一个值对它们进行了排序。因此,它已将第二件放在首饰中,但没有进行其他分类。
或者,如果我按照这里提倡的程序(Sorting in pandas for large datasets),首先对各个部分进行排序然后合并,我似乎得到了正确的结果:
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在使用合并选项时能够可靠地执行它所声称的内容?手册文本是否暗示某些情况下这个程序无法达到预期效果?
答案 0 :(得分:1)
Gnu sort(至少是我查看源代码的版本),将在内存中对文件的块进行排序并创建一组临时文件(每个块一个临时文件)。它还在内存排序阶段使用多线程(命令行参数可以设置要使用的最大线程数)。在创建所有临时文件之后,它会对临时文件执行16路合并(除非您覆盖它),直到它生成单个排序文件。
这里的要点是你不必先将文件拆分成单独的文件,因为gnu sort会自动处理一个大文件,根据需要创建排序的临时文件,以合并到一个已排序的文件中。
-m选项适用于要合并多个已排序文件的特殊情况。
答案 1 :(得分:1)
我怀疑概念上的问题与“合并”的含义有关。在排序算法的上下文中,“合并”具有特定含义。有关讨论,请参见https://en.wikipedia.org/wiki/Merge_algorithm。关键一点是,尽管合并操作确实需要多个文件作为输入,但是任何单个输入文件中的项目都必须按照正确的排序顺序进行合并才能达到预期的目的-这与排序不同操作。从这个意义上说,“合并不会排序”。
还有一种称为“合并排序”的排序算法,该算法将合并操作用作其组件之一。
答案 2 :(得分:0)
-m
只是将文件合并在一起,就像mergesort的merge
操作一样。它需要按照相同的顺序对两个文件进行排序。
因此,为了对非常大的文件进行排序,您所做的工作确实有效:将其拆分为几个较小的文件,在本地对它们进行排序。此时,如果你只是将每个文件追加到另一个文件,你最终会得到0 1 2 3 ... 0 1 2 3
-m
选项会合并它们。
例如,那些:
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