当前位置:  开发笔记 > 编程语言 > 正文

Bash脚本中范围内的随机数

如何解决《Bash脚本中范围内的随机数》经验,为你挑选了10个好方法。

我需要在2000-65000shell脚本之间生成一个随机端口号.问题是$RANDOM15位数,所以我卡住了!

PORT=$(($RANDOM%63000+2001)) 如果不是因为尺寸限制,它会很好地工作.

有没有人有一个如何做到这一点的例子,可能是从/dev/urandom一个范围内提取并得到它?



1> leedm777..:
shuf -i 2000-65000 -n 1

请享用!

编辑:范围包含在内.


我认为`shuf`是相对较新的 - 我在过去几年在Ubuntu系统上看过它,但目前的RHEL/CentOS并没有.
@Dennis Williamson:使用`-n 1`运行测试显示可忽略不计的时差,即使是`end = 4000000000`.很高兴知道`shuf`很聪明,而不是很难:-)
我的mac上没有shuf :(
此外,它可能适合这种用途,但我相信`shuf`实际上确实可以置换整个输入.如果您经常生成随机数,这将是一个糟糕的选择.
@Jefromi:在我的系统上,在{1..1000}中使用此测试`i的时间; do shuf -i 0- $ end -n 1000>/dev/null; 完成`并将`end = 1`与`end = 65535`进行比较表明较短范围的改善约为25%,相当于超过一百万次迭代的约4秒差异.它比**执行OP的Bash计算快一百万倍.
@VirenShakya - 如果您安装[Homebrew](http://mxcl.github.com/homebrew/),那么您可以`brew install coreutils`.使用前缀`g`安装命令,因此它将是`gshuf`.
缺省情况下,“ shuf” [不使用加密安全的随机数生成器](https://www.gnu.org/software/coreutils/manual/html_node/Random-sources.html)。如果需要的话,添加`--random-source = / dev / urandom`。

2> 小智..:

在Mac OS X和FreeBSD上你也可以使用jot:

jot -r 1  2000 65000


在这个例子中,`jot`对于区间的最小值和最大值(即2000和65000)具有不公平的分布.换句话说,min和max的生成频率会降低.有关详细信息和解决方法,请参阅我的[jot answer](http://unix.stackexchange.com/a/241199/141917).

3> 小智..:

根据bash手册页,$RANDOM分布在0到32767之间; 也就是说,它是一个无符号的15位值.假设$RANDOM均匀分布,您可以创建一个均匀分布的无符号30位整数,如下所示:

$(((RANDOM<<15)|RANDOM))

由于你的范围不是2的幂,简单的模运算几乎只能给你一个均匀的分布,但是输入范围是30位,输出范围小于16位,就像你的情况一样,这应该足够接近:

PORT=$(( ((RANDOM<<15)|RANDOM) % 63001 + 2000 ))


只能给你一个均匀的分布,但是输入范围是30位,输出范围小于16位,就像你的情况一样,这应该足够接近:

4> ghostdog74..:

这是Python的一个

randport=$(python -S -c "import random; print random.randrange(2000,63000)")

和一个与awk

awk 'BEGIN{srand();print int(rand()*(63000-2000))+2000 }'


这个得到了我的支持.我为各种系统编写bash脚本,我相信awk可能是这项工作最丰富的工具.在没有问题的情况下使用mac os x和centos,我知道它也可以在我的debian机器上运行,也可能是任何其他普通的ish*nix机器.
但是,awk的随机种子似乎只刷新一次/秒,因此您可能希望a)不惜一切代价避免或b)重新初始化种子.

5> Cascabel..:

想到的最简单的一般方法是perl one-liner:

perl -e 'print int(rand(65000-2000)) + 2000'

你总是可以使用两个数字:

PORT=$(($RANDOM + ($RANDOM % 2) * 32768))

你仍然需要剪辑到你的范围.它不是一般的n位随机数方法,但它适用于你的情况,而且它都在bash中.

如果你想要非常可爱并从/ dev/urandom中读取,你可以这样做:

od -A n -N 2 -t u2 /dev/urandom

那将读取两个字节并将它们打印为unsigned int; 你仍然需要剪裁.



6> valadil..:

这是另一个.我认为它几乎可以用于任何事情,但是我的centos盒子里没有sort的随机选项.

 seq 2000 65000 | sort -R | head -n 1


`sort -R`在OS X上也不可用.

7> 小智..:

你可以这样做

cat /dev/urandom|od -N2 -An -i|awk -v f=2000 -v r=65000 '{printf "%i\n", f + r * $1 / 65536}'

如果需要更多详细信息,请参阅Shell脚本随机数生成器.



8> Renato Silva..:

$RANDOM是0到32767之间的数字。您需要2000到65000之间的端口。这是63001个可能的端口。如果我们将值保持$RANDOM + 2000200033500之间,则可以覆盖31501个端口。如果我们掷硬币,然后有条件地将31501添加到结果中,我们可以获得更多的端口,从3350165001。然后,如果我们仅丢弃65001,就可以得到所需的确切覆盖范围,并且所有端口的概率分布均匀。

random-port() {
    while [[ not != found ]]; do
        # 2000..33500
        port=$((RANDOM + 2000))
        while [[ $port -gt 33500 ]]; do
            port=$((RANDOM + 2000))
        done

        # 2000..65001
        [[ $((RANDOM % 2)) = 0 ]] && port=$((port + 31501)) 

        # 2000..65000
        [[ $port = 65001 ]] && continue
        echo $port
        break
    done
}

测试中

i=0
while true; do
    i=$((i + 1))
    printf "\rIteration $i..."
    printf "%05d\n" $(random-port) >> ports.txt
done

# Then later we check the distribution
sort ports.txt | uniq -c | sort -r



9> Berto..:

如果您不是bash专家,并且希望将其转换为基于Linux的bash脚本中的变量,请尝试以下操作:

VAR=$(shuf -i 200-700 -n 1)

这将使您获得200到700的范围$VAR,包括在内.



10> Lev Lukomsky..:

与红宝石相同:

echo $(ruby -e 'puts rand(20..65)') #=> 65 (inclusive ending)
echo $(ruby -e 'puts rand(20...65)') #=> 37 (exclusive ending)

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有