
日常生活中,会经常用到随机数,使用场景非常广泛,例如买彩票、丢骰子、抽签、年会抽奖等。Shell下如何生成随机数呢,小编特意写了本文,总结LinuxShell产生随机数的多种方法。
计算机产生的的只是“伪随机数”,不会产生绝对的随机数(是一种理想随机数)。实际上,伪随机数和理想随机数也是相对的概念,例如伪随机数在1万万亿亿亿年内也无法重复,算是理想随机数么?
伪随机数在大量重现时也并不一定保持唯一,但一个好的伪随机产生算法将可以产生一个非常长的不重复的序列,例如UUID(通用唯一识别码)在100亿年内才可用完。
1.使用系统的$RANDOM变量(CentOS、Ubuntu、MacOS都支持,但只有5位数随机)
mimvp@ubuntu:~$echo$RANDOM17617
$RANDOM的范围是[0,32767]
示例:使用for循环来验证:
_random(){foriin{1..10};doecho-e"$i\t$RANDOM"done}print_random
运行结果:
!/bin/bash随机数+范围上限,然后取余randnum=$(($num%$mid+$min))shmimvp_shell_
这里,还可以通过awk产生随机数,最大为6位随机数,其跟时间有关,系统时间一致则随机数都相同,没有$RANDOM随机性好
awk'BEGIN{srand();printrand()*1000000}'855767
2.使用date+%s%N(CentOS、Ubuntu支持,MacOS不支持纳秒+%N)
通过Linux/Unix的时间戳来获取随机数
获取秒数,2位数43获取时间戳,10位数,从1970-01-0100:00:00到当前的间隔的秒数1548739004获取纳秒值,9位数,CentOS、Ubuntu支持,但MacOS不支持468529240
说明:
如果用时间戳date+%s做随机数,相同一秒的数据是一样的。在做循环处理多线程时,基本不能满足要求
如果用纳秒值date+%N做随机数,精度达到了亿分之一,相当精确了,在多cpu高并发的循环里,同一秒里也很难出现相同结果,不过也会有重复碰撞的可能性
如果用时间戳+纳秒值date+%N%s做组合随机数(10+9=19位数),则比较完美了,重复的概率大大降低,但注意:MacOS系统不支持纳秒值,不算通用
示例:生成40,000,000~50,000,000的随机数
时间戳随机数functionmimvp_randnum_date(){min=$1max=$2mid=$(($max-$min+1))num=$(date+%s%N|cut-c1-17)随机数包含上下限边界数值echo$randnum}functionprint_randnum_date(){foriin{1..10};dorandnum=$(mimvp_randnum_date000000)echo-e"$i\t$randnum"done}print_randnum_date
运行结果:
head-20/dev/urandom|cksum353502489150260!/bin/bashnum=$(head-n20/dev/urandom|cksum|cut-d''-f1)num=$(head-n20/dev/urandom|cksum|awk'{print$1}')num=$(head-n20/dev/urandom|cksum|awk-F""'{print$1}')shmimvp_shell_42014734
由此可见,用随机文件生成的随机数,基本是全随机的,且通用于CentOS、Ubuntu、MacOS
4.使用linuxuuid(CentOS、Ubuntu支持,MacOS不支持)
UUID(UniversallyUniqueIdentifier,通用唯一识别码),格式包含32个16进制数字,以'-'连接号分为5段。
格式为8-4-4-4-12的32个字符,例如:07e7-98bb-a3bf7c96e34a
!/bin/bashshmimvp_shell_
5.使用opensslrand(CentOS、Ubuntu支持、MacOS都支持,需安装openssl,推荐)
opensslrand用于产生指定长度个bytes的随机字符
opensslrand-base648opensslrand-base648opensslrand-base648|cksumopensslrand-base648|md5sumopensslrand-base648|cksum|cut-c1-8opensslrand-base648|md5sum|cut-c1-8opensslrand-hex8opensslrand-hex8opensslrand-hex8|cksumopensslrand-hex8|md5sumopensslrand-hex8|cksum|cut-c1-8opensslrand-hex8|md5sum|cut-c1-8!/bin/bash-base64-hexrandnum=$(($num%$mid+$min))echo$randnum}functionprint_randnum_openssl(){foriin{1..10};dorandnum=$(mimvp_randnum_openssl000000)echo-e"$i\t$randnum"done}print_randnum_openssl
运行结果:
自定义一个数字数组num=${获取数组的长度(元素个数)
randnum=${array[$((RANDOM%num))]}!/bin/bash整数的位数,依据取值范围设定,默认最长为18位整数(取决于正整数的范围)STR_ARRAY=(0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)生成整数str_array_count=${字符串数组的元素个数,62=10+26+26randnum_array[@]}NUM_LENGTH的长度:18打印出全部数组元素,如B2ytzKcZsNl9TbVwj6num='1'echo"num:$num"shmimvp_shell_
7.生成随机字符串
上述所有可以生成随机整数的方法,都可以生成随机字符串,原理是对随机整数进行md5sum计算
示例:生成10位随机字符串
使用/dev/urandom生成随机字符串cat/dev/urandom|head-n10|md5sum|head-c10
随机数应用一
随机生成端口号范围为1025~65536(通用于CentOS,Ubuntu,MacOS),并支持排除任意添加的端口号
应用的随机数是方法3.使用/dev/random和/dev/urandom随机文件
应用代码:
应用一:随机生成端口号1025~65536(通用于CentOS,Ubuntu,MacOS)functionmimvp_app_port(){min=$1max=$2mid=$(($max-$min+1))num=$(head-n20/dev/urandom|cksum|cut-f1-d'')randnum=$(($num%$mid+$min))shmimvp_shell_
随机数应用二
随机生成长度为10的密码字符串(通用于CentOS,Ubuntu,MacOS)
应用的随机数是方法1:使用系统的$RANDOM变量
应用代码:
应用二:随机生成长度为10的密码字符串(通用于CentOS,Ubuntu,MacOS)functionmimvp_app_passwd(){user_array=`seq-w10`echo${user_array[@]}foridxin${user_array[@]}douser_name="user-${idx}"passwd=`echo$RANDOM|md5sum|cut-c11-20`echo-e"${user_name}\t${passwd}"done}mimvp_app_passwd
运行结果:
!/bin/bash对6取余,余数为0时记作6点case"$randnum"in0)stat_6=`expr${stat_6}+1`;;shmimvp_shell__1923stat_2994stat_3977stat_41039stat_51072stat_6995
总结
date日期生成的随机数,与Linux系统的随机设备/dev/random的关系不大,但系统时间也会影响/dev/random设备,两者并非绝对无关系。
所有可以生成随机整数的方法,都可以生成随机字符串,原理是对随机整数进行md5sum计算
最后,附上完整的shell代码,方便爱好者研究、调试
系统默认随机数functionprint_randnum(){foriin{1..10};dorandnum=$RANDOMrandnum=$(awk'BEGIN{srand();printrand()*1000000;}')随机数+范围上限,然后取余randnum=$(($num%$mid+$min))19位数,截取第1-17位数,下标从1开始num=$(date+%s%N)随机数包含上下限边界数值echo$randnum}functionprint_randnum_date(){foriin{1..10};dorandnum=$(mimvp_randnum_date000000)echo-e"$i\t$randnum"done}3.Linux随机文件functionmimvp_randnum_file(){min=$1max=$2mid=$(($max-$min+1))num=$(head-n20/dev/urandom|cksum|cut-f1-d'')okokokrandnum=$(($num%$mid+$min))echo$randnum}functionprint_randnum_file(){foriin{1..10};dorandnum=$(mimvp_randnum_file000000)echo-e"$i\t$randnum"done}4.Linuxuuidfunctionmimvp_randnum_uuid(){min=$1max=$2mid=$(($max-$min+1))num=$(head-n20/proc/sys/kernel/random/uuid|cksum|cut-f1-d'')randnum=$(($num%$mid+$min))echo$randnum}functionprint_randnum_uuid(){foriin{1..10};dorandnum=$(mimvp_randnum_uuid000000)echo-e"$i\t$randnum"done}5.Linuxopensslfunctionmimvp_randnum_openssl(){min=$1max=$2mid=$(($max-$min+1))num=$(opensslrand-base648|cksum|cut-f1-d'')num=$(opensslrand-hex8|cksum|cut-f1-d'')整数的位数,依据取值范围设定,默认最长为18位整数(取决于正整数的范围)STR_ARRAY=(0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)生成整数str_array_count=${字符串数组的元素个数,62=10+26+26randnum_array[@]}NUM_LENGTH的长度:18打印出全部数组元素,如B2ytzKcZsNl9TbVwj6num='1'echo"num:$num"排除的端口号1080,4500,8080,58866,可以任意添加port_exclude='1080,4500,8080,58866'flag=`echo${port_exclude}|grep${randnum}|wc-l`while["$flag"-eq"1"]donum=$(head-n20/dev/urandom|cksum|cut-f1-d'')randnum=$(($num%$mid+$min))flag=`echo${port_exclude}|grep${randnum}|wc-l`doneecho$randnum}functionprint_app_port(){foriin{1..10};dorandnum=$(mimvp_app_port102565535)echo-e"$i\t$randnum"done}应用二:随机生成长度为10的密码字符串(通用于CentOS,Ubuntu,MacOS)functionmimvp_app_passwd(){user_array=`seq-w10`echo${user_array[@]}foridxin${user_array[@]}douser_name="user-${idx}"passwd=`echo$RANDOM|md5sum|cut-c11-20`echo-e"${user_name}\t${passwd}"done}应用三:统计掷骰子,投掷6000次统计分别为1-6的次数(通用于CentOS,Ubuntu,MacOS)functionmimvp_app_dice(){MAX=6000stat_1=0stat_2=0stat_3=0stat_4=0stat_5=0stat_6=0i=1while["$i"-le"$MAX"]dorandnum=$(($RANDOM%6))余数为0时记作6点1)stat_1=`expr${stat_1}+1`;;2)stat_2=`expr${stat_2}+1`;;3)stat_3=`expr${stat_3}+1`;;4)stat_4=`expr${stat_4}+1`;;5)stat_5=`expr${stat_5}+1`;;esaclet"i=i+1"doneecho"stat_1${stat_1}"echo"stat_2${stat_2}"echo"stat_3${stat_3}"echo"stat_4${stat_4}"echo"stat_5${stat_5}"echo"stat_6${stat_6}"}print_randnumprint_randnum_dateprint_randnum_uuidprint_randnum_arraymimvp_app_passwd循环次数多,运行时间较长,大约30秒,请慎用
版权声明:本站所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,不声明或保证其内容的正确性,如发现本站有涉嫌抄袭侵权/违法违规的内容。请举报,一经查实,本站将立刻删除。