使用种子洗牌 bash 中的数字

Shuffling numbers in bash using seed

我想创建一个整数数组,其中的数字从 1...N 开始。每个数字在此数组中出现一次。例如 array = {1, 3, 5, 2, 4} 当 N = 5.

为了生成这个数组,我使用了 shuffle 方法:

        array=($(shuf -i 1-$N -n $N ))

它工作正常。但是,我想在此代码中添加种子,以确保每次 运行 使用相同种子的代码时,我都会得到相同的数组。是否可以使用 shuffle 方法来做到这一点?

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

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

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

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

要以不依赖 string-splitting(以及 IFS 的当前值)的方式将结果加载到 bash 数组中,您的实现可能如下所示:

# with bash 4.0 or newer
readarray -t array < <(shuf -i1-100 --random-source=<(get_seeded_random 42))

# or, supporting bash 3.x as well
IFS=$'\n' read -r -d '' -a array \
  < <(shuf -i1-100 --random-source=<(get_seeded_random 42) && printf '[=11=]')

单独使用 bash(不使用 shufopenssl 等外部工具,您可以使用 $RANDOM,您可以使用 pseudo-random 输入播种,例如所以:

RANDOM=$$

RANDOM=$(date '+%s')

等等

您可以使用 {1..N}.

等表达式 select 一系列数字
declare -a a=()
for n in {1..5}; do
    a[$RANDOM]=$n
done
echo "${a[@]}"

上面编码的这个解决方案在重复随机值的情况下有 non-zero 失败的风险,这可以通过一些额外的代码来减轻,或者通过扩展随机范围来减少,例如使用 bit-shifting 生成 30 位无符号整数而不是 15 位无符号整数:

...
    a[$(( (RANDOM<<15)+RANDOM ))]=$n
...

此解决方案的输出是 "randomized",因为在 bash 中,non-associative 数组的元素自然按其索引值进行数字排序。

请注意,"sequential" 也是一个有效的随机顺序。 :-)

$ a=(); for n in {1..5}; do a[$RANDOM]=$n; done; declare -p a
declare -a a=([7460]="5" [12697]="3" [16841]="2" [21485]="1" [32493]="4")
$ a=(); for n in {1..5}; do a[$RANDOM]=$n; done; declare -p a
declare -a a=([1444]="1" [12162]="2" [17774]="3" [29827]="4" [31840]="5")