我正在尝试在 Bash 中生成一个符合 MacOS 密码要求的密码,其中之一是它不能包含重复的字符(aa、bb、44、00 等)。
我知道我可以使用
openssl rand -base64
或 /dev/urandom
并使用 tr -d
来操作输出字符串。我使用 grep -E '(.)\1{1,}'
搜索重复字符,但如果我使用此正则表达式删除 (tr -d (.)\1{1,}'
),它会删除整个字符串。我什至尝试 tr -s '(.)\1{1,}'
将字符压缩到仅出现一次,但在某些尝试中它不断生成重复的字符。有可能实现我想要的目标吗?
P.S.:在这种情况下,我无法下载任何“密码生成器工具”,例如 pwgen 等。一定是“本土”
有具体尺寸要求吗?其他需要的字符吗?
怎么样-
openssl rand -base64 20 | sed -E 's/(.)\1+/\1/g'
如果您有强制执行的最小密码长度范围 -
openssl rand -base64 $((13+RANDOM%10)) | sed -En 'H; ${ x; s/\n//g; s/(.)\1+/\1/g; s/^(.{10,25}).*/\1/; p; }'
(更新添加输出长度护栏)
抱歉,我无能为力,但我想帮助你。
如何迭代地获取唯一的字符,例如。通过
chars=$(openssl rand -base64)
pwd=
for (( i=0; i<${#chars}; i++ )); do
if [[ "$(echo $pwd | grep "${chars:$i:1}")" == "" ]]; then
pwd=$pwd${chars:$i:1}
fi
done
问题可能是您有不可打印的字符,因此它不会“实际上”重复。如果你第一次得到第一个,例如30 个字符,然后删除任何非字母数字、非标点符号字符,然后挤压任何这些字符,然后从剩下的内容中获取前 20 个字符,这似乎有效:
cat /dev/urandom | tr -dc '[:alnum:][:punct:]' | fold -w ${1:-30} | head -n 1 | tr -s '[:alnum:][:punct:]' | cut -c-20
输出例如:
]'Zc,fs6m;wUo%wLIG%K
2O3Ff4dzi30~L.RH8jR0
sU?,WkK]&I;z'|eTSLjY
5gK]\H51i@Rtux.{bdC=
:g"\?5JsjBd1r])2^WR+
;{cR:jY\rIc&Q(2yo:|-
fFykmxvZ|ATX_l6L(8h:
^Sd*,V%9}bWnTYNv"w?'
6foMgbU6:n<*cWj2W=3&
*v39FWmB@LwE5O`a3C36
其中任何一个都会挤压重复:
tr -cs '\0'
tr -s '[:graph:][:space:]'
它们的区别仅在于我们如何引用“所有字符”。第一个是“null 的补集”,第二个是所有可打印字符和所有空白字符。可能有一种更简洁的方法来指定“所有字符”。
或使用 sed:
sed -E 's/(.)\1+/\1/g'
这既挤压了可打印字符,又删除了空格:
tr -ds '[:space:]' '[:graph:]'
32 个非空白字符且无重复的示例:
tr -ds '[:space:]' '[:graph:]' < /dev/urandom |
dd bs=32 count=1
此外,此示例指定允许的字符列表(字母、数字和
_.
),然后压缩任何重复:
tr -dc '[:alnum:]_.' < /dev/urandom |
tr -sc '\0' |
dd bs=32 count=1
输出示例:
9mCEqrhHPwmq7.1qEky6qn4jqzDpRK7b
将 dd 放在末尾意味着我们在删除重复之后得到 32 个字符。您可能还想添加
status=none
来隐藏 stderr 上的 dd 日志记录。
#! /bin/bash
awk -vN=20 '
{
n=split($0,ch,"");
for (i=1; i<n; i++) {
a[ch[i]]++
}
n=0;
for (c in a) {
if (++n > N) {
break;
}
printf("%c",c)
}
printf("\n")
}
' < <(openssl rand -base64 32)
N
长度的密码,没有重复的字符(即 N 应该远小于 32
)