子外壳中对 $RANDOM 的引用都返回相同的值

References to $RANDOM in subshells all returning identical values

以下简短脚本打印一个随机的十位二进制数:

#!/usr/bin/zsh
point=''
for i in `seq 1 10`
do
    echo $RANDOM >/dev/null
    point=$point`if [ $RANDOM -gt 16383 ]; then echo 0; else echo 1; fi`
done
echo $point

但是,如果我删除明显无用的 echo $RANDOM >/dev/null 行,脚本总是打印 11111111110000000000.

为什么?

来自手册页:

The values of RANDOM form an intentionally-repeatable pseudo-random sequence; subshells that reference RANDOM will result in identical pseudo-random values unless the value of RANDOM is referenced or seeded in the parent shell in between subshell invocations.

echo 的 "useless" 调用提供了一个引用,允许由命令替换引起的子 shell 每次都产生不同的值。

Subshells(由反引号或其现代替代品 $() 创建)在与父 shell 不同的上下文中执行——这意味着当它们退出时,所有进程本地状态更改——包括随机数生成器的状态——被丢弃。

从父 shell 内部的 $RANDOM 读取更新 RNG 的状态,这就是 echo $RANDOM >/dev/null 有效的原因。

也就是说,不要那样做。做这样的事情,它根本没有 subshells:

point=
for ((i=0; i<10; i++)); do
  point+=$(( (RANDOM > 16383) ? 0 : 1 ))
done

如果您测试它生成超过 10 个数字——比如尝试 1000 或 10000——您还会发现它的性能比原来的要好得多。