来自 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
Random number from a range in a Bash Script
提问by Jason Gooner
I need to generate a random port number between 2000-65000
from a shell script. The problem is $RANDOM
is a 15-bit number, so I'm stuck!
我需要在2000-65000
shell 脚本之间生成一个随机端口号。问题是$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/urandom
and 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, $RANDOM
is distributed between 0 and 32767; that is, it is an unsigned 15-bit value. Assuming $RANDOM
is 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
$RANDOM
is 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 + 2000
between 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 个可能的端口。如果我们坚持2000和33500$RANDOM + 2000
之间的值,我们将覆盖 31501 端口的范围。如果我们抛硬币,然后有条件地将 31501 添加到结果中,我们可以获得更多端口,从33501到65001。然后,如果我们只删除 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 脚本随机数生成器。