Bash脚本中某个范围内的随机数
我需要从shell脚本生成一个介于Bash脚本中某个范围内的随机数,bash,shell,scripting,Bash,Shell,Scripting,我需要从shell脚本生成一个介于2000-65000之间的随机端口号。问题是,$RANDOM是一个15位的数字,所以我卡住了 PORT=$($RANDOM%63000+2001))如果没有大小限制,它会工作得很好 有没有人举个例子来说明我是如何做到这一点的,也许可以从/dev/uradom中提取一些东西,并将其放在一个范围内?想到的最简单的通用方法是perl一行程序: perl -e 'print int(rand(65000-2000)) + 2000' 您始终可以使用两个数字: PORT
2000-65000
之间的随机端口号。问题是,$RANDOM
是一个15位的数字,所以我卡住了
PORT=$($RANDOM%63000+2001))
如果没有大小限制,它会工作得很好
有没有人举个例子来说明我是如何做到这一点的,也许可以从
/dev/uradom
中提取一些东西,并将其放在一个范围内?想到的最简单的通用方法是perl一行程序:
perl -e 'print int(rand(65000-2000)) + 2000'
您始终可以使用两个数字:
PORT=$(($RANDOM + ($RANDOM % 2) * 32768))
你仍然需要根据自己的范围进行剪辑。这不是一个通用的n位随机数方法,但它适用于您的情况,并且都在bash中
如果您想变得非常可爱并阅读/dev/uradom,您可以这样做:
od -A n -N 2 -t u2 /dev/urandom
这将读取两个字节,并将它们打印为无符号整数;你还得做剪辑
shuf -i 2000-65000 -n 1
享受吧
编辑:范围是包含的。这里有一个Python
randport=$(python -S -c "import random; print random.randrange(2000,63000)")
还有一个是awk
awk 'BEGIN{srand();print int(rand()*(63000-2000))+2000 }'
在Mac OS X和FreeBSD上,您也可以使用jot:
jot -r 1 2000 65000
这是另一个。我原以为它几乎可以在任何东西上工作,但sort的随机选项在我的centos机器上都不可用
seq 2000 65000 | sort -R | head -n 1
你可以这样做
cat /dev/urandom|od -N2 -An -i|awk -v f=2000 -v r=65000 '{printf "%i\n", f + r * $1 / 65536}'
如果您需要更多详细信息,请参阅。或在OS-X上,以下内容适用于我:
$ gsort --random-sort
export CUDA_VISIBLE_DEVICES=$((( RANDOM % 8 )))
PORT=$($RANDOM%63000+2001))
已经接近您想要的了
PORT=$($RANDOM$RANDOM$RANDOM%63000+2001))
绕过了困扰您的大小限制。因为bash对数字变量和字符串变量没有区别,所以它工作得非常好。“number”$RANDOM
可以像字符串一样连接起来,然后在计算中用作数字。太棒了 每次引用$RANDOM
时,都会返回一个介于0和32767之间的随机数。如果我们对两个连续的引用求和,我们会得到0到65534之间的值,这涵盖了2000到65000之间随机数的63001个可能的期望范围
为了将其调整到精确的范围,我们使用求和模63001,它将给我们一个从0到63000的值。这反过来只需要增加2000,以提供所需的随机数,介于2000和65000之间。这可以概括如下:
port=$((((RANDOM + RANDOM) % 63001) + 2000))
$(((RANDOM<<15)|RANDOM))
测试
# Generate random numbers and print the lowest and greatest found
test-random-max-min() {
max=2000
min=65000
for i in {1..10000}; do
port=$((((RANDOM + RANDOM) % 63001) + 2000))
echo -en "\r$port"
[[ "$port" -gt "$max" ]] && max="$port"
[[ "$port" -lt "$min" ]] && min="$port"
done
echo -e "\rMax: $max, min: $min"
}
# Sample output
# Max: 64990, min: 2002
# Max: 65000, min: 2004
# Max: 64970, min: 2000
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
计算的正确性
下面是一个完整的蛮力测试,以验证计算的正确性。该程序只是尝试使用测试中的计算,随机生成所有63001种不同的可能性。--jobs
参数应使其运行更快,但它不是确定性的(生成的可能性总数可能低于63001)
为了确定需要多少次迭代才能获得生成的所有63001个可能性的给定概率p/q
,我相信我们可以使用下面的表达式。例如,和
根据bash手册页,
$RANDOM
分布在0和32767之间;也就是说,它是一个无符号的15位值。假设$RANDOM
是均匀分布的,您可以创建均匀分布的无符号30位整数,如下所示:
port=$((((RANDOM + RANDOM) % 63001) + 2000))
$(((RANDOM<<15)|RANDOM))
$(((RANDOM$RANDOM
是一个介于0和32767之间的数字。您需要一个介于2000和65000之间的端口。这些是63001个可能的端口。如果我们坚持$RANDOM+2000
介于2000和33500之间的值,我们覆盖了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
}
测试
# Generate random numbers and print the lowest and greatest found
test-random-max-min() {
max=2000
min=65000
for i in {1..10000}; do
port=$((((RANDOM + RANDOM) % 63001) + 2000))
echo -en "\r$port"
[[ "$port" -gt "$max" ]] && max="$port"
[[ "$port" -lt "$min" ]] && min="$port"
done
echo -e "\rMax: $max, min: $min"
}
# Sample output
# Max: 64990, min: 2002
# Max: 65000, min: 2004
# Max: 64970, min: 2000
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
如果您不是bash专家,并且希望将其放入基于Linux的bash脚本中的变量中,请尝试以下方法:
VAR=$(shuf-i200-700-n1)
这将使您的范围从200到700,包括$VAR
。您可以通过uradom
head-200/dev/uradom | cksum
输出:
3310670062 52870
检索上述编号的一部分
head-200/dev/uradom | cksum | cut-f1-d”“
然后输出为
3310670062
为了满足您的要求
head-200/dev/uradom | cksum | cut-f1-d“| awk'{print$1%63000+2001}”
这是我通常生成随机数的方式。然后我使用“NUM_1”作为我使用的端口号的变量。下面是一个简短的示例脚本
#!/bin/bash
clear
echo 'Choose how many digits you want for port# (1-5)'
read PORT
NUM_1="$(tr -dc '0-9' </dev/urandom | head -c $PORT)"
echo "$NUM_1"
if [ "$PORT" -gt "5" ]
then
clear
echo -e "\x1b[31m Choose a number between 1 and 5! \x1b[0m"
sleep 3
clear
exit 0
fi
!/bin/bash
清楚的
echo“选择端口#(1-5)所需的位数”
读取端口
NUM_1=“$(tr-dc'0-9'与ruby相同:
echo $(ruby -e 'puts rand(20..65)') #=> 65 (inclusive ending)
echo $(ruby -e 'puts rand(20...65)') #=> 37 (exclusive ending)
这对我很有用:
$ gsort --random-sort
export CUDA_VISIBLE_DEVICES=$((( RANDOM % 8 )))
如果希望从1开始而不是从0开始,可以添加1。我认为shuf
是相对较新的-我在过去几年在Ubuntu系统上见过它,但在当前的RHEL/CentOS上没有见过。同样,这种用法可能很好,但我相信shuf
实际上会改变整个输入。如果你是非常频繁地生成随机数。@Dennis Williamson:使用-n1
运行测试时,即使end=4000000000
,时间差也可以忽略不计。很高兴知道shuf
工作起来很聪明,不难:-)我的mac电脑上没有shuf:(@VirenShakya-如果您安装,那么您就可以brew安装coreutils
。命令的安装前缀为g
,因此它将是gshuf
。我明白您的意思。我同意发行版会有所不同,但您无论如何都无法获得真正的随机性。有时使用$RANDOM,有时使用$RANDOM$RAN可能更好DOM,有时是$RANDOM$RANDOM$RANDOM,以获得更均匀的分布。据我所知,更多的$RANDOM有利于更高的端口号。(我删除了我的原始注释,因为我使用了一些错误的数字。)