bash中大于32767的数组中的随机元素

时间:2017-04-07 09:42:31

标签: arrays bash random

有:

mapfile -t words < <( head -10000 /usr/share/dict/words)
echo "${#words[@]}" #10000
r=$(( $RANDOM % ${#words[@]} ))
echo "$r ${words[$r]}"

这从10k字的数组中选择一个随机字。

但是如果数组大32767(例如整个文件200k +单词),它会停止工作,因为$RANDOM最多只有32767.来自man bash

  

每次引用此参数时,都会生成0到32767之间的随机整数。

mapfile -t words < /usr/share/dict/words
echo "${#words[@]}" # 235886
r=$(( $RANDOM % ${#words[@]} )) #how to change this?
echo "$r ${words[$r]}"

不要使用像perl -plE 's/.*/int(rand()*$_)/e'这样的perl,并不是每个系统都安装了perl。寻找最简单的解决方案 - 也不关心真正的随机性 - 它不适用于加密。 :)

3 个答案:

答案 0 :(得分:1)

如果您的系统上有shuf ...

r=$(shuf -i 0-${#words[@]} -n 1)

如果没有,您可以多次使用$RANDOM并连接结果以获得足够数字的数字来满足您的需求。你应该连接,而不是添加,因为添加随机数不会产生均匀分布(就像投掷两个随机模具将产生总共7个而不是总共1个)。

例如:

printf -v r1 %05d $RANDOM
printf -v r2 %05d $RANDOM
printf -v r3 %05d $RANDOM
r4=${r1:1}${r2:1}${r3:1}
r=$(( $r4 % ${#words[@]} ))

printf语句用于确保保留前导零; -v选项是一个隐藏的gem,它允许为变量赋值(除了其他功能之外,它允许在许多有用的实际案例中避免使用eval)。 r1r2r3各自的第一个数字被删除,因为它只能是0,1,2或3。

答案 1 :(得分:1)

一种可能的解决方案是使用$RANDOM的结果进行一些数学运算:

big_random=`expr $RANDOM \* 32767 + $RANDOM`

另一种方法是使用$RANDOM一次选择输入文件的块,然后再次使用$RANDOM从该块中选择一行。

请注意,$RANDOM不允许您指定范围。 %给出了不统一的结果。进一步讨论:How to generate random number in Bash?

顺便说一句,将整个words读入记忆中并不是特别明智。除非您要对此数据结构进行大量重复访问,否则请考虑尝试在不立即填充整个文件的情况下执行此操作。

答案 2 :(得分:0)

接受的答案将为您提供10位数字,但是对于每个5位数字的前缀,后5位数字只能在00000-32767范围内。

例如,1234567890不可能是数字67890 > 32767

可能很好。我个人觉得这个选项更好。它为您提供数字0-1073676289,没有空格。

big_random=$(expr $RANDOM \* $RANDOM)