[英]Best way to generate a random string following a specific pattern in Bash
[英]Using "$RANDOM" to generate a random string in Bash
我正在尝试使用 Bash 变量$RANDOM
创建一个随机字符串,该字符串由来自包含 integer 和字母数字的变量的 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
对于那些在 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
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
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
使用稀疏数组来打乱字符。
#!/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
有点晦涩但写起来很短的解决方案是
RANDSTR=$(mktemp XXXXX) && rm "$RANDSTR"
期望您对当前目录具有写入权限;-) mktemp
是 coreutils 的一部分
更新:正如 Bazi 在评论中指出的那样,可以在不创建文件的情况下使用 mktemp ;-) 所以命令可以更短。
RANDSTR=$(mktemp --dry-run XXXXX)
使用tr
和dd
:
chars='abcd1234ABCD'
length='8'
tr -cd "$chars" </dev/urandom | dd bs=1 count="$length" 2>/dev/null
echo
基于Radu Gabriel 的回答并使用 GNU bash 版本 4.4.20 测试并set -euxo pipefail
的缩写安全 pipe 解决方法:
head -c 20 <(tr -dc [:alnum:] < /dev/urandom)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.