用固定种子拖曳文件的行?

时间:2011-05-06 16:47:52

标签: bash sorting

我想用固定的种子来重排文件的行,这样我总能得到相同的随机顺序。我使用的命令如下:

sort -R file.txt | head -200 > file.sff

我可以做些什么改变,以便用固定的随机种子进行排序?

3 个答案:

答案 0 :(得分:7)

sort的GNU实现有一个--random-source参数。将此参数与具有已知内容的文件的名称一起传递将产生可靠的输出集。

请参阅GNU coreutils手册中的Random sources文档,其中包含以下示例实现和示例:

get_seeded_random()
{
  seed="$1"
  openssl enc -aes-256-ctr -pass pass:"$seed" -nosalt \
    </dev/zero 2>/dev/null
}

shuf -i1-100 --random-source=<(get_seeded_random 42)

由于GNU sort也是coreutils的一部分,相关文档也适用于此:

sort --random-source=<(get_seeded_random 42) -R file.txt | head -200 > file.sff

答案 1 :(得分:1)

您可能不需要使用sort等外部工具,其选项和用法可能因操作系统而异。 Bash有一个内部随机数生成器,可通过$RANDOM变量访问。通常的做法是通过设置变量来生成发生器,如下所示:

RANDOM=$$

RANDOM=$(date '+%s')

等。但是,当然,您也可以使用可预测的种子来获得可预测的不那么随机的结果:

$ RANDOM=12345; echo $RANDOM
28207
$ RANDOM=12345; echo $RANDOM
28207

要随机重新排序映射文件的行,可以使用mapfile将文件读入数组:

$ mapfile -t a < source.txt

然后只需重写数组索引:

$ for i in ${!a[@]}; do a[$((RANDOM+${#a[@]}))]="${a[$i]}"; unset a[$i]; done

当读取非关联数组时,bash自然地按索引值的升序对元素进行排序。

请注意,每行的 new 索引都添加了数组元素,以避免在该范围内发生冲突。这个解决方案仍然是错误的 - 不能保证$RANDOM将产生唯一的数字。您可以使用额外的代码来检查每个索引的先前使用,或通过位移来降低风险,从而降低风险:

... a[$(( (RANDOM<<15)+RANDOM+${#a[@]} ))]= ...

这使您的索引值成为30位无符号整数而不是15位无符号整数。

答案 2 :(得分:-4)

如果你随机洗牌,你就不会排序。我之前没有看到sort --random-source提示符。它确实存在会很有趣。但是,这不是按固定顺序对行进行排序。

我相信你必须写一个程序,我不认为Bash可以做到这一点。

实际上,它可能会。 $ RANDOM环境变量选择0到32767之间的随机数。您可以将种子分配给RANDOM,随机数序列将反复出现。您可以使用card dealing algorithm。将每行读入Bash数组,然后使用卡处理算法选择每一行。

我不会写一个测试程序 - 特别是在Bash中,但你应该明白这个想法。