使用种子在bash中拖曳数字

时间:2017-01-31 16:20:17

标签: bash random gnu-coreutils

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

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

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

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

2 个答案:

答案 0 :(得分:2)

shuf的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)

要以不依赖于字符串拆分(以及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 '\0')

答案 1 :(得分:1)

仅在bash中(不使用shufopenssl等外部工具,您可以使用$RANDOM,您可以使用伪随机输入播种,如下所示:

RANDOM=$$

RANDOM=$(date '+%s')

您可以使用{1..N}等表达式选择一系列数字。

declare -a a=()
for n in {1..5}; do
    a[$RANDOM]=$n
done
echo "${a[@]}"

如上所述,此解决方案在重复随机值的情况下具有非零风险,可通过一些额外代码缓解,或通过扩展随机范围来减少,例如使用位移来制作30 -bit无符号整数,而不是15位无符号整数:

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

使用此解决方案的输出是“随机的”,因为在bash中,非关联数组的元素按其索引的值自然地按数字顺序排列。

请注意,“顺序”也是有效的随机顺序。 : - )

$ 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")