我有一个文件太大而不适合内存。 shuf
似乎在RAM中运行,并且sort -R
不混洗(相同的行最后彼此相邻;我需要将所有行混在一起)。除了滚动我自己的解决方案之外,还有其他选择吗bash - 将一个文件太大而无法放入内存中
回答
使用decorate-sort-undecorate模式的一种形式,awk
你可以这样做:
$ seq 10 | awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' | sort -n | cut -c8-
8
5
1
9
6
3
7
2
10
4
对于一个文件,你会怎么做:
$ awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' SORTED.TXT | sort -n | cut -c8- > SHUFFLED.TXT
或cat
管道开始处的文件。
这个工作方式是生成一列000000
和999999
之间的随机数字(装饰);在该列上排序(排序);然后删除列(undecorate)。这应该在排序不理解数字的平台上工作,方法是生成一个具有前导零的列以进行词典排序。
您可以增加随机化,如果需要的话,在几个方面:
如果你的平台的
sort
了解数值(POSIX,GNU和BSD这样做),你可以做awk 'BEGIN{srand();} {printf "%0.15f\t%s\n", rand(), $0;}' FILE.TXT | sort -n | cut -f 2-
使用接近双浮子随机表示。如果您仅限于词典排序,只需将两个调用合并到一个列中,如下所示:
awk 'BEGIN{srand();} {printf "%06d%06d\t%s\n", rand()*1000000,rand()*1000000, $0;}' FILE.TXT | sort -n | cut -f 2-
它提供了一个12位数的随机组合。
计数行(wc -l
)并按随机顺序生成与行号相对应的数字列表 - 可能是通过生成临时文件中的数字列表(使用/tmp/
,通常位于RAM中,因此速度相对较快)。然后按照混洗号码的顺序将每个号码对应的行复制到目标文件中。
由于在文件中寻找换行符的数量,这样做效率会很低,但它几乎适用于任何大小的文件。
如何: perl <large-input-file -lne 'print rand(), "\t", $_' | sort | perl -lpe 's/^.*?\t//' >shuffled-output-file
如果文件中有什么可以装入内存大小的几个数量级之内,一个选择是随机分配中(比如说)1000个临时文件中的行,然后洗牌每个这些文件并连接结果:
perl -we ' my $NUM_FILES = 1000;
my @fhs;
for (my $i = 0; $i < $NUM_FILES; ++$i) {
open $fh[$i], "> tmp.$i.txt"
or die "Error opening tmp.$i.txt: $!";
}
while (<>) {
$fh[int rand $NUM_FILES]->print($_);
}
foreach my $fh (@fhs) {
close $fh;
}
' < input.txt \
&& \
for tmp_file in tmp.*.txt ; do
shuf ./"$tmp_file" && rm ./"$tmp_file"
done > output.txt
(当然,也将在临时文件—的尺寸有一些变化,他们不会全部是正好千分之一原始文件—的大小,因此,如果您使用这种方法,你需要在更多方面犯错,更小的文件)。
赦免最初的误读 - 我希望downvoter不相信我错误的分析。这是一个完全合理的方法。 –
@CharlesDuffy:不用担心。我*猜测* downvoter实际上是l'L'l。 (即使不是,我现在认为dawg的答案比我的答案更好,所以我不太关心这个答案。:-P) – ruakh
看看https://github.com/alexandres/terashuf。从页面:
terashuf实现了利用有限的内存
- 1. 我的JSON文件太大而无法放入内存,我该怎么办?
- 2. rmd文件太大而无法打开
- 3. 将.html中的变量传递给.php文件太大而无法放入URL中?
- 4. 如何在XML数据太大而无法放入内存时访问Java中XML数据的子集?
- 5. 无法打开,无法写入:文件太大
- 6. 无法通过phpmyadmin文件大小导入数据库太大
- 7. 时间戳太大,无法保存在一个int变量中
- 8. 合并大文件而不将整个文件加载到内存中?
- 9. 将大文件放入列表中
- 10. Keras处理无法放入内存的大型数据集
- 11. 当文件无法放入火花的主内存中时,火花如何读取大文件(petabye)
- 12. 计算文件中的行数而不将整个文件读入内存?
- 13. 内存问题downloding一个大文件
- 14. 在python中加载一个.csv文件,消耗太多内存
- 15. 将方法的结果放入另一个.m文件中
- 16. 将文件读入内存?
- 17. 缓存内存中的一个大文件的java中
- 18. 我想将一个XML文件内容放入一个URL中,我可以吗?
- 19. 不能用安全的FTP将文件放入内存中
- 20. couchbase无法存储,因为太大
- 21. 如何查看太大而无法在编辑器中打开的.sql文件?
- 22. CLOB值太大,无法插入DB2表
- 23. 无法释放内存C
- 24. 计划是太大,无法在内存Pyinstaller
- 25. 使用UTI将文件的内容放入NSPasteboard而非NSFileContentsPboardType?
- 26. 把csv文件放入内存
- 27. Bash:递归地将一行写入列最大的文件
- 28. 无法将输出放入一个变量
- 29. 将大文件写入Blob存储和内存不足
- 30. 无法将文件夹从一个项目拖放到xcode4中的另一个
尼斯洗牌 多TB的文本文件准洗牌算法。因为'sort'分成多个文件来处理大于内存的内容(GNU版本,无论如何),这实际上应该工作。 –
+1 - 好主意。请注意,因为'sort'执行稳定的排序,所以这不会是100%完美的洗牌:如果A行在输入的B行之前,这种方法稍微有可能在行B之前将A行放在输出中。为了解决这个问题,你可以通过编写诸如'seq 10 |的东西来反转编号和混洗grep -n''| sort -R |切掉-d:-f2-'代替。 (但即使没有这种变化,我认为它可能是好的:我认为它应该非常接近随机排序。) – ruakh
@ruakh:谢谢。你是对的 - 由于“排序”具有稳定的排序,所以它略有维持秩序的倾向。它具有0到1000000之间的随机数字,因此这只会是连续两行中相同随机数的问题。另一种更加随机的方法是添加更多数字或第二列随机数字。 – dawg