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

Dan*_*ner 3 random shell zsh

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

#!/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
Run Code Online (Sandbox Code Playgroud)

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

为什么?

che*_*ner 6

从手册页:

RANDOM的值形成有意重复的伪随机序列; 除非在子shell调用之间在父shell中引用或播种RANDOM的值,否则引用RANDOM的子shell将产生相同的伪随机值.

"无用"调用echo提供了引用,该引用允许命令替换引起的子shell每次产生不同的值.


Cha*_*ffy 5

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

从$RANDOM父外壳内部读取会更新RNG的状态,这就是为什么RNG会echo $RANDOM >/dev/null起作用的原因。

就是说,不要那样做。做这样的事情,根本没有子shell:

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

如果您测试此生成的数字是否超过10位(例如,尝试使用1000或10000),您还会发现它的性能远胜于原始数字。

  • 绝对使用无子壳代码;我只是专注于解释观察到的行为。 (2认同)