【发布时间】:2015-09-09 16:11:01
【问题描述】:
我正在尝试使用 Bash 变量 $RANDOM 创建一个随机字符串,该字符串由来自包含整数和字母数字的变量的 8 个字符组成,例如 var="abcd1234ABCD"。
我该怎么做?
【问题讨论】:
我正在尝试使用 Bash 变量 $RANDOM 创建一个随机字符串,该字符串由来自包含整数和字母数字的变量的 8 个字符组成,例如 var="abcd1234ABCD"。
我该怎么做?
【问题讨论】:
使用参数扩展。 ${#chars} 是可能的字符数,% 是模运算符。 ${chars:offset:length} 选择位置 offset 的字符,即在我们的例子中为 0 - length($chars)。
chars=abcd1234ABCD
for i in {1..8} ; do
echo -n "${chars:RANDOM%${#chars}:1}"
done
echo
【讨论】:
chars 包含转义字符,这可以启动bash 命令l。试试chars='<=>| -,;:!/."()[]{}*\&#%+012345689abcdefghiklmnopqrstuvwxyz'
对于那些在 bash 中寻找随机字母数字字符串的人:
LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 64
与有据可查的函数相同:
function rand-str {
# Return random alpha-numeric string of given LENGTH
#
# Usage: VALUE=$(rand-str $LENGTH)
# or: VALUE=$(rand-str)
local DEFAULT_LENGTH=64
local LENGTH=${1:-$DEFAULT_LENGTH}
LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c $LENGTH
# LC_ALL=C: required for Mac OS X - https://unix.stackexchange.com/a/363194/403075
# -dc: delete complementary set == delete all except given set
}
【讨论】:
另一种生成32字节(例如)十六进制字符串的方法:
xxd -l 32 -c 32 -p < /dev/random
如果您想要大写字符,请添加 -u。
【讨论】:
选项 1 - 没有特定的长度,不需要 openssl,只有字母和数字,比 选项 2 慢
sed "s/[^a-zA-Z0-9]//g" <<< $(cat /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%*()-+' | fold -w 32 | head -n 1)
演示:x=100; while [ $x -gt 0 ]; do sed "s/[^a-zA-Z0-9]//g" <<< $(cat /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%*()-+' | fold -w 32 | head -n 1) <<< $(openssl rand -base64 17); x=$(($x-1)); done
例子:
j0PYAlRI1r8zIoOSyBhh9MTtrhcI6d
nrCaiO35BWWQvHE66PjMLGVJPkZ6GBK
0WUHqiXgxLq0V0mBw2d7uafhZt2s
c1KyNeznHltcRrudYpLtDZIc1
edIUBRfttFHVM6Ru7h73StzDnG
选项 2 - 没有特定长度,openssl 需要,只有字母和数字,比选项 1 快
openssl rand -base64 12 # only returns
rand=$(openssl rand -base64 12) # only saves to var
sed "s/[^a-zA-Z0-9]//g" <<< $(openssl rand -base64 17) # leave only letters and numbers
# The last command can go to a var too.
演示:x=100; while [ $x -gt 0 ]; do sed "s/[^a-zA-Z0-9]//g" <<< $(openssl rand -base64 17); x=$(($x-1)); done
例子:
9FbVwZZRQeZSARCH
9f8869EVaUS2jA7Y
V5TJ541atfSQQwNI
V7tgXaVzmBhciXxS
【讨论】:
没有使用$RANDOM,但值得一提。
使用 shuf 作为熵源(又名随机性)(反过来,可以使用 /dev/random 作为熵源。如 `shuf -i1-10 --random-source=/dev/urandom)看起来像使用更少资源的解决方案:
$ shuf -er -n8 {A..Z} {a..z} {0..9} | paste -sd ""
tf8ZDZ4U
【讨论】:
head -1 <(fold -w 20 <(tr -dc 'a-zA-Z0-9' < /dev/urandom))
如果您打开了安全选项,在 bash 脚本中使用它是安全的:
set -eou pipefail
这是使用管道时 bash 退出状态 141 的解决方法
tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 20 | head -1
【讨论】:
使用 sparse 数组来打乱字符。
#!/bin/bash
array=()
for i in {a..z} {A..Z} {0..9}; do
array[$RANDOM]=$i
done
printf %s ${array[@]::8} $'\n'
(或大量随机字符串)
#!/bin/bash
b=()
while ((${#b[@]} <= 32768)); do
a=(); for i in {a..z} {A..Z} {0..9}; do a[$RANDOM]=$i; done; b+=(${a[@]})
done
tr -d ' ' <<< ${b[@]} | fold -w 8 | head -n 4096
【讨论】: