linux 如何生成一个没有重复字符的随机字符串?

vecaoik1  于 2022-12-03  发布在  Linux
关注(0)|答案(5)|浏览(155)

我试图在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和更多.它必须是“原生”

cigdeys3

cigdeys31#

对不起,我没有什么事要忙,但我想帮你。
如何迭代地获取唯一字符,例如通过

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
ruoxqz4g

ruoxqz4g2#

问题可能是你有不可打印的字符,所以它不是 * 实际 * 重复的。如果你首先得到前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
x8diyxa7

x8diyxa73#

是否有具体的大小要求?其他要求的字符?
不如...

openssl rand -base64 20 | sed -E 's/(.)\1+/\1/g'
b1zrtrql

b1zrtrql4#

tr不使用正则表达式(但使用POSIX字符类)。
这两种方法中的任何一种都将挤压重复:

tr -cs '\0'
tr -s '[:graph:][:space:]'

它们的不同之处仅在于我们如何引用“所有字符”。首先是“空的补充”,其次是所有可打印字符和所有白色字符。可能有一种更简洁的方法来指定“所有字符”。
或者使用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来隐藏dd在stderr上的日志记录。

dly7yett

dly7yett5#

不清楚您是否不希望连续字符重复或根本不希望重复字符(* 无论是哪种情况,我都不认为这是一个好主意,因为这会使您的密码更弱,更容易猜测 *),但话虽如此

#! /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)

这会从32个随机字节中生成长度为N且不含重复字符的密码(* 即N应远小于32*)

相关问题