题目:一句 Shell 脚本,使用 2G 内存,排序一个 10G 的文件。
准备工作
首先,我们用 Python 脚本计算一个 10G 的文件最大的整数是多少(因为硬盘的原因就以 10M 为例),10M 得到的结果是 1449607。
# First approache
total = 1024*1024*10
total -= 2
count = 0
for i in range(1, 100000):
size = (10**i-10**(i-1))*(i+1)
if total >= size:
total -= size
count = i
else:
break
print (total/(count+2)) - 1 + 10**count
print "Remain Bytes: ", total%(count+2)
# Second approache
# 只做小数据时验证使用
total = 1024*1024*10
for i in range(0, 10000000):
total -= len(str(i)) + 1
if total < 0:
print i-1
print "Remain Bytes: ", total+ len(str(i)) + 1
break
然后,调用 seq 和 shuf(在 OS X 下可以先执行 brew install coreutils 安装软件包,然后使用 shuf)命令生成打乱的文件。
seq -f '%0.f' 0 1449607 > old_dat
gshuf old_data -o old_data2
- 如果不放心自己生成文件的大小,可以用 Hex Field 查看一下:
具体 Shell 的编写
由于 sort 命令会把所有传递给它的数字存在内存里排序,所以把所有的内容分为几部分进行排序可以减少 sort 所占用的内存。虽然多扫了几次文件,但是内存可以少占用很多。由于我们最大的数字就是 1449607,还不到 2M 个数字,所以每次处理 1M 的话,分两次就搞定了。
for i in `seq 0 1`;
do awk 'BEGIN{i='$i'}{if($1>=1024*i && $1<1024*(i+1))print $0}' old_data2 | sort -g >> new_data;
done;
最后,比较一下排序出的文件与最初的文件是否相同,相同就说明我们的命令写对了。
diff old_data new_data
最后
这还只是一个很粗浅的方法,但是摸索的过程中学到了很多 Shell 的知识。后续可能会找个工具测一下 sort 命令的执行效率,进而给出更准确的答案。
相关链接
- EOF -