对较大的文件进行排序会出现分段错误

对较大的文件进行排序会出现分段错误
mkdir tmp
sort -u *.txt -T tmp/ -o output.txt

只有几十 GB 大小的文件需要排序。

问题是几分钟后排序会出现分段错误。

操作系统是最新的 Scientific Linux 6.6。

问题:如何对文件进行“排序 -u”? Sort 无法处理较大的文件?.. 当发生段错误时,RAM 未满一半.. 只有一个核心处于 100%

答案1

过去,我不得不对太大的文件进行排序sort。我认为这也是您的问题,但如果您提供更多信息,也许我们可以更好地诊断您的问题。

grep我的问题的解决方案是用预处理器来分解文件。查看您的数据以了解团块的位置。我假设它在字母数字空间中分布得很好,但稍后我将讨论如何处理簇。

for char1 in other {0..9} {a..z}; do
  out="/tmp/sort.$char1"
  echo "Extracting lines starting with '$char1'"
  if [ "$char1" = "other" ]; then char1='[^a-z0-9]'; fi
  grep -i "^$char1" *.txt > "$out"
  sort -u "$out" >> output.txt || break
done

(这使用了 bashism。为了避免它,请明确命名 37 个字符中的每一个,例如for char1 in other 0 1 2 3 4 5 6 7 8 9 0 a b c d e f ...

团块:由于数据太多,这些循环调用中的一些可能sort会出现段错误。只需修改迭代以将其分解为多个部分即可。这可能很简单,只需删除 grep 的-i标志并调出每个大写字母(不要忘记将 改为other[^a-zA-Z0-9],或者可能需要深入研究数据。如果这是软件包列表,则可能有太多以“lib”开头的行,因此迭代/tmp/sort.l将失败。|| break此循环的一部分将在此时停止处理,因此您可以修复它并从上次中断的地方继续。按照“lib”示例,您可能希望使用类似以下内容继续:

for char1 in 'l[a-h]' 'lia' lib{a..z} lib{0..9} 'li[c-z]' 'l[j-z]' {m..z}; do
  ...

这会将l列表分为 lib* 部分之前和之后的部分。它有点难看,但应该可以。只需注意所需的顺序即可保存它。

答案2

另一种可能性是分别对每个文件进行排序,然后合并它们:

for f in *txt; do
    sort -u "$f" -T tmp/ > "$f".sorted
done
sort -mu *sorted

-m选项会sort合并已排序的文件,而不是尝试对它们进行排序。这应该会导致内存使用量低得多,并且应该避免段错误。

答案3

结合不同的答案:当您想对文件进行分段排序时,请尝试使用 split:

LARGETMP=/var/tmp
mkdir ${LARGETMP}
N_LINES=100000 # Adjust when to still too large or too small
split --lines=${N_LINES} bigfile splitted_
for small in splitted*; do
   sort -u -T ${LARGETMP} ${small} > sorted_${small}
   rm ${small}
done
echo "Done with sorting the splitted files, now concate the stuff"
sort -um -T ${LARGETMP} sorted_* > bigfile.sorted

编辑:正如 @ua2b 评论的那样,按大小分割主要会在行中间分割。
(当文件没有换行时,整个排序的想法有点奇怪)。

答案4

我在OpenBSD上找到了一种方法:

http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/sort.1?query=sort&sec=1

 -H
    Use a merge sort instead of a radix sort. This option should be used for files larger than 60MB.

但这不是一个完全好的解决方案,因为它占用了太多空间... x>100 GByte 还不够。

相关内容