我的文件太大而无法放入内存中。 shuf
似乎在RAM中运行,并且sort -R
没有随机播放(相同的行最终彼此相邻;我需要对所有行进行混洗)。除了推出自己的解决方案之外还有其他选择吗?
答案 0 :(得分:8)
使用decorate-sort-undecorate模式和$ 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
和sort
之间的随机数列(装饰)来实现;对该列进行排序(排序);然后删除列(undecorate)。这应该适用于sort不能理解数字的平台,方法是生成一个带有前导零的列用于词典排序。
如果需要,您可以通过多种方式增加随机化:
如果您的平台的awk 'BEGIN{srand();} {printf "%0.15f\t%s\n", rand(), $0;}' FILE.TXT | sort -n | cut -f 2-
理解数值(POSIX,GNU和BSD),您可以rand
使用近似双浮点进行随机表示。
如果您仅限于词典排序,只需将对awk 'BEGIN{srand();} {printf "%06d%06d\t%s\n", rand()*1000000,rand()*1000000, $0;}' FILE.TXT | sort -n | cut -f 2-
的两次调用合并为一列,如下所示:var json = [{cover:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Internet2.jpg/440px-Internet2.jpg", album:"test1"},{cover:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Internet2.jpg/440px-Internet2.jpg", album:"test2"}];
for (var x = 0; x<json.length;x++){
var fig = document.createElement("figure");
var figCap = document.createElement("figcaption");
figCap.innerText = json[x].album;
var image = document.createElement("img");
image.id = "picture";
image.width = 100;
image.height = 100;
image.src = json[x].cover;
var display = document.getElementById("results");
fig.appendChild(image);
fig.appendChild(figCap);
display.appendChild(fig);
}
,它会给出12位数的随机化数据。
答案 1 :(得分:3)
计算行(wc -l
)并以随机顺序生成与行号对应的数字列表 - 可能是通过生成临时文件中的数字列表(使用/tmp/
,其中包含RAM通常,因此相对较快)。然后按照随机数字的顺序将对应于每个数字的行复制到目标文件。
这会节省时间,因为在文件中寻找新行的数量很多,但它几乎适用于任何大小的文件。
答案 2 :(得分:1)
看看https://github.com/alexandres/terashuf。来自页面:
terashuf实现了一种用于改组的准混洗算法 使用有限内存的多TB文本文件
答案 3 :(得分:0)
怎么样:
perl <large-input-file -lne 'print rand(), "\t", $_' | sort | perl -lpe 's/^.*?\t//' >shuffled-output-file
答案 4 :(得分:0)
如果文件在内存中可以容纳几个数量级,那么一个选项就是在(比方说)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
(当然,临时文件的大小会有一些变化 - 它们都不会完全原始文件大小的千分之一 - 所以如果你使用这种方法,你需要通过错误的更小的文件来给自己一些缓冲。)
答案 5 :(得分:0)
首先,我想说,这不是严格的全局改组解决方案。
通常,我的想法是将大文件分成较小的文件,然后进行随机播放。
split -bytes=500M large_file small_file_
这会将您的large_file拆分为small_file_aa,small_file_ab ....
shuf small_file_aa > small_file_aa.shuf
您可以尝试多次混合文件以获得近似于全局随机播放的结果。