Linux Shell 生成随机数和随机字符串

原创

Linux Shell 生成随机数和随机字符串

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/sunboy_2050/article/details/86777411
            </div>
                                                <!--一个博主专栏付费入口-->
         
         <!--一个博主专栏付费入口结束-->
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-4a3473df85.css">
                                    <div id="content_views" class="markdown_views prism-atom-one-dark">
                <!-- flowchart 箭头图标 勿删 -->
                <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                    <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                </svg>
                                        <p>日常生活中,会经常用到随机数,使用场景非常广泛,例如买彩票、丢骰子、抽签、年会抽奖等。</p>

Shell 下如何生成随机数呢,米扑博客特意写了本文,总结 Linux Shell 产生随机数的多种方法。

本文原文转自米扑博客:Linux Shell 生成随机数和随机字符串

计算机产生的的只是“伪随机数”,不会产生绝对的随机数(是一种理想随机数)。实际上,伪随机数和理想随机数也是相对的概念,例如伪随机数在1万万亿亿亿年内也无法重复,算是理想随机数么?

伪随机数在大量重现时也并不一定保持唯一,但一个好的伪随机产生算法将可以产生一个非常长的不重复的序列,例如 UUID(通用唯一识别码)在100亿年内才可用完。

1. 使用系统的 $RANDOM 变量(CentOS、Ubuntu、MacOS 都支持,但只有5位数随机)

mimvp@ubuntu:~$ echo $RANDOM 17617

$RANDOM 的范围是 [0, 32767]

**示例:**使用 for 循环来验证:

#!/bin/bash # mimvp.com 2016.05.10

function print_random() { for i in {1…10}; do echo -e “$i \t $RANDOM” done }

print_random

运行结果:

# sh mimvp_shell_rand.sh 1 20191 2 16817 3 25971 4 1489 5 34 6 25183 7 920 8 315 9 18845 10 29519

如需要生成超过32767的随机数,可以用以下方法实现(有缺陷)

例:生成 40,000,000~50,000,000 的随机数,但最后末尾五位数在随机变化,实现原理有缺陷

#!/bin/bash # mimvp.com 2016.05.10

## Linux 系统随机数 + 范围上限值后, 再取余 function mimvp_random_bignum() { min=$1 max= 2 m i d = 2 m i d = 2 m i d = 2mid=2mid= 2 mid= 2mid=2mid=2mid=(mimvp_randnum_openssl4000000050000000)echoe"i \t $randnum" done }

print_randnum_openssl

运行结果:

# sh mimvp_shell_rand.sh 1 43422505 2 40756492 3 45087076 4 43882168 5 47105153 6 45505018 7 41411938 8 48662626 9 47508094 10 41362566

6. 自定义数组生成随机数

自定义一个数组,用于生成一段特定长度(整数最长为18位)的有数字和字母组成的字符串,字符串中元素取自自定义的池子。

array=(0 1 2 3 4 5 6 7 8 9) # 自定义一个数字数组

num=${#array[*]} # 获取数组的长度(元素个数)

randnum=KaTeX parse error: Expected 'EOF', got '}' at position 30: …ror: Expected '}̲', got '\[' at …((RANDOM%num))]} # 利用Linux系统默认的 $RANDOM 随机数,随机从数组选择一个元素,构成新的长度数组

**示例:**自定义数组生成 40,000,000~50,000,000 之间的随机数(注释有点不好看,但非常有助于理解代码哈)

#!/bin/bash # mimvp.com 2016.05.10

## 6. custom array, 可以生成整数, 字符串 function mimvp_randnum_array() { NUM_LENGTH=18 # 整数的位数, 依据取值范围设定, 默认最长为18位整数(取决于正整数的范围) STR_ARRAY=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) # 生成字符串 STR_ARRAY=(0 1 2 3 4 5 6 7 8 9) # 生成整数

str\_array\_count=${#STR_ARRAY\[@\]}    # 字符串数组的元素个数, 62 = 10 + 26 + 26
  • 1
  • 2

# echo “str_array_count: ${str_array_count}”

i=1
while \[ "$i" -le "${NUM_LENGTH}" \];
do
    randnum\_array\[$i\]=${STR\_ARRAY\[$((RANDOM%str\_array\_count))\]}
    let "i=i+1"
done
randnum\_array\_count=${#randnum_array\[@\]}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

# echo “randnum_array_count: ${randnum_array_count}” # NUM_LENGTH 的长度: 18 # echo “randnum_array: ${randnum_array[@]}” # 打印出全部数组元素, 如 B 2 y t z K c Z s N l 9 T b V w j 6

num='1'             # 整数首位不能是0, 因此直接固定为1, 防止整数时首位为0的异常错误
for item in ${randnum_array\[@\]};
do
    num="${num}${item}"
done
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

# echo “num: $num” # 1B2ytzKcZsNl9TbVwj6

min=$1
max=$2
mid=$(($max-$min+1))
randnum=$(($num%$mid+$min))        
echo $randnum
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

}

function print_randnum_array() { for i in {1…10}; do randnum=KaTeX parse error: Expected 'EOF', got '&' at position 44: …50000000)echo−e&̲quot;(mimvp_ran…nummid+$min))

# 排除的端口号 1080, 4500, 8080, 58866, 可以任意添加
port_exclude='1080,4500,8080,58866'
flag=\`echo ${port_exclude} | grep ${randnum} | wc -l\`
while \[ "$flag" -eq "1" \]
do
    num=$(head -n 20 /dev/urandom | cksum | cut -f1 -d ' ')
    randnum=$(($num%$mid+$min))        
    flag=\`echo ${port_exclude} | grep ${randnum} | wc -l\`
done
echo $randnum
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

}

function print_app_port() { for i in {1…10}; do randnum=KaTeX parse error: Expected 'EOF', got '&' at position 32: …02565535)echo−e&̲quot;(mimvp_app…(mimvp_app_port102565535)echoe"i \t $randnum" done }

print_app_port

运行结果:

# sh mimvp_shell_rand.sh
1 29483 2 61738 3 31935 4 3242 5 19865 6 56677 7 5944 8 28579 9 12510 10 31844

随机数应用二

随机生成长度为10的密码字符串 (通用于 CentOS, Ubuntu, MacOS)

应用的随机数是 方法1:使用系统的 $RANDOM 变量

应用代码:

#!/bin/bash # mimvp.com 2016.05.10

## 应用二: 随机生成长度为10的密码字符串 (通用于 CentOS, Ubuntu, MacOS) function mimvp_app_passwd() { user_array=`seq -w 10` echo ${user_array[@]}

for idx in ${user_array\[@\]}
do
    user_name="user-${idx}"
    passwd=\`echo $RANDOM | md5sum | cut -c11-20\`
    echo -e "${user_name} \\t ${passwd}"
done
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

}

mimvp_app_passwd

运行结果:

# sh mimvp_shell_rand.sh
01 02 03 04 05 06 07 08 09 10 user-01 52cf5272cb user-02 40f20d352d user-03 9fe9a7b770 user-04 ff4e20e6e0 user-05 88fc4a3ea3 user-06 6494032261 user-07 6a42732519 user-08 6fc7a25dd5 user-09 f0b6a95608 user-10 49219467fa

随机数应用三

统计掷骰子,投掷6000次统计分别为1-6的次数 (通用于 CentOS, Ubuntu, MacOS)

应用的随机数是 方法1:使用系统的 $RANDOM 变量

应用代码:

#!/bin/bash # mimvp.com 2016.05.10

## 应用三: 统计掷骰子, 投掷6000次统计分别为1-6的次数 (通用于 CentOS, Ubuntu, MacOS) function mimvp_app_dice() { MAX=6000 stat_1=0 stat_2=0 stat_3=0 stat_4=0 stat_5=0 stat_6=0

i=1
while \[ "$i" -le "$MAX" \]
do
    randnum=$(($RANDOM%6))  # 对6取余, 余数为0时记作6点
    case "$randnum" in
        0) stat\_6=\`expr ${stat\_6} + 1\`;;    # 余数为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\`;;
    esac
    let "i=i+1"
done

echo “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}”

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

}

mimvp_app_dice

运行结果:

# sh mimvp_shell_rand.sh
stat_1 923 stat_2 994 stat_3 977 stat_4 1039 stat_5 1072 stat_6 995

总结

random、urandom、uuid、openssl rand、自定义数组(用到了 $RANDOM)产生随机码的伪数据来源,都与 /dev/random 设备有关系,只是它们各自呈现不同。

date 日期生成的随机数,与Linux 系统的随机设备 /dev/random 的关系不大,但系统时间也会影响 /dev/random 设备,两者并非绝对无关系。

所有可以生成随机整数的方法,都可以生成随机字符串,原理是对随机整数进行 md5sum 计算

最后,附上完整的 shell 代码,方便爱好者研究、调试

#!/bin/bash # mimvp.com 2016.05.10

## 1. Linux 系统默认随机数 function print_randnum() { for i in {1…10}; do randnum=KaTeX parse error: Expected 'EOF', got '#' at position 41: …ed 'EOF', got '#̲' at position 8…(awk ‘BEGIN{srand(); print rand()*1000000; }’) # awk 随机种子函数, 最多5位随机数, 跟时间有关 echo -e “$i \t $randnum” done }

## Linux 系统随机数 + 范围上限值后, 再取余 function mimvp_randnum_bignum() { min=$1 max= 2 m i d = 2 m i d = 2 m i d = 2mid=2mid= 2 mid= 2mid=2mid=2mid=(mimvp_randnum_openssl4000000050000000)echoe"i \t $randnum" done }

## 6. custom array, 可以生成整数, 字符串 function mimvp_randnum_array() { NUM_LENGTH=18 # 整数的位数, 依据取值范围设定, 默认最长为18位整数(取决于正整数的范围) STR_ARRAY=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) # 生成字符串 STR_ARRAY=(0 1 2 3 4 5 6 7 8 9) # 生成整数

str\_array\_count=${#STR_ARRAY\[@\]}    # 字符串数组的元素个数, 62 = 10 + 26 + 26
  • 1
  • 2

# echo “str_array_count: ${str_array_count}”

i=1
randnum_array=()
while \[ "$i" -le "${NUM_LENGTH}" \];
do
    randnum\_array\[$i\]=${STR\_ARRAY\[$((RANDOM%str\_array\_count))\]}
    let "i=i+1"
done
randnum\_array\_count=${#randnum_array\[@\]}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

# echo “randnum_array_count: ${randnum_array_count}” # NUM_LENGTH 的长度: 18 # echo “randnum_array: ${randnum_array[@]}” # 打印出全部数组元素, 如 B 2 y t z K c Z s N l 9 T b V w j 6

num='1'             # 整数首位不能是0, 因此直接固定为1, 防止整数时首位为0的异常错误
for item in ${randnum_array\[@\]};
do
    num="${num}${item}"
done
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

# echo “num: $num” # 1B2ytzKcZsNl9TbVwj6

min=$1
max=$2
mid=$(($max-$min+1))
randnum=$(($num%$mid+$min))        
echo $randnum
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

}

function print_randnum_array() { for i in {1…10}; do randnum=KaTeX parse error: Expected 'EOF', got '&' at position 44: …50000000)echo−e&̲quot;(mimvp_ran…nummid+$min))

# 排除的端口号 1080, 4500, 8080, 58866, 可以任意添加
port_exclude='1080,4500,8080,58866'
flag=\`echo ${port_exclude} | grep ${randnum} | wc -l\`
while \[ "$flag" -eq "1" \]
do
    num=$(head -n 20 /dev/urandom | cksum | cut -f1 -d ' ')
    randnum=$(($num%$mid+$min))        
    flag=\`echo ${port_exclude} | grep ${randnum} | wc -l\`
done
echo $randnum
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

}

function print_app_port() { for i in {1…10}; do randnum=KaTeX parse error: Expected 'EOF', got '&' at position 32: …02565535)echo−e&̲quot;(mimvp_app…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值