来自 Bash 脚本范围的随机数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2556190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:07:11  来源:igfitidea点击:

Random number from a range in a Bash Script

bashshellscripting

提问by Jason Gooner

I need to generate a random port number between 2000-65000from a shell script. The problem is $RANDOMis a 15-bit number, so I'm stuck!

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

PORT=$(($RANDOM%63000+2001))would work nicely if it wasn't for the size limitation.

PORT=$(($RANDOM%63000+2001))如果不是因为尺寸限制,效果会很好。

Does anyone have an example of how I can do this, maybe by extracting something from /dev/urandomand getting it within a range?

有没有人有我如何做到这一点的例子,也许通过从中提取一些东西/dev/urandom并将其置于一个范围内?

回答by leedm777

shuf -i 2000-65000 -n 1

Enjoy!

享受!

Edit: The range is inclusive.

编辑:范围包括在内。

回答by errno

On Mac OS X and FreeBSD you may also use jot:

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

jot -r 1  2000 65000

回答by Jesin

According to the bash man page, $RANDOMis distributed between 0 and 32767; that is, it is an unsigned 15-bit value. Assuming $RANDOMis uniformly distributed, you can create a uniformly-distributed unsigned 30-bit integer as follows:

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

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

Since your range is not a power of 2, a simple modulo operation will only almostgive you a uniform distribution, but with a 30-bit input range and a less-than-16-bit output range, as you have in your case, this should really be close enough:

由于您的范围不是 2 的幂,因此简单的模运算几乎只能为您提供均匀分布,但具有 30 位输入范围和小于 16 位输出范围,就像您的情况一样,这真的应该足够接近了:

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

回答by ghostdog74

and here's one with Python

这是一个 Python

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

and one with awk

和一个 awk

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

回答by Cascabel

The simplest general way that comes to mind is a perl one-liner:

想到的最简单的通用方法是 perl one-liner:

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

You could always just use two numbers:

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

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

You still have to clip to your range. It's not a general n-bit random number method, but it'll work for your case, and it's all inside bash.

你仍然需要调整到你的范围。它不是一般的 n 位随机数方法,但它适用于您的情况,并且都在 bash 中。

If you want to be really cute and read from /dev/urandom, you could do this:

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

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

That'll read two bytes and print them as an unsigned int; you still have to do your clipping.

这将读取两个字节并将它们打印为无符号整数;你仍然需要做你的剪辑。

回答by Berto

If you're not a bash expert and were looking to get this into a variable in a Linux-based bash script, try this:

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

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

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

That gets you the range of 200 to 700 into $VAR, inclusive.

这使您获得 200 到 700 的范围$VAR,包括 。

回答by Renato Silva

$RANDOMis a number between 0 and 32767. You want a port between 2000 and 65000. These are 63001 possible ports. If we stick to values of $RANDOM + 2000between 2000and 33500, we cover a range of 31501 ports. If we flip a coin and then conditionally add 31501 to the result, we can get more ports, from 33501to 65001. Then if we just drop 65001, we get the exact coverage needed, with a uniform probability distribution for all ports, it seems.

$RANDOM是一个介于 0 和 32767 之间的数字。您需要一个介于 2000 和 65000 之间的端口。这些是 63001 个可能的端口。如果我们坚持200033500$RANDOM + 2000之间的值,我们将覆盖 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
}

Testing

测试

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

回答by Lev Lukomsky

Same with ruby:

与红宝石相同:

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

回答by valadil

Here's another one. I thought it would work on just about anything, but sort's random option isn't available on my centos box at work.

这是另一个。我认为它几乎可以用于任何事情,但是 sort 的随机选项在我的 Centos 机器上不可用。

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

回答by New Exit

You can do this

你可以这样做

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

If you need more details see Shell Script Random Number Generator.

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