1

本来应该是一个简单的 bash 脚本,结果却变成了怪物。这是第五次尝试。您甚至不想看到尝试 #4 的 30 行怪物.. :)

这是我想要做的:脚本生成一个随机密码,$1=密码长度,$2=输出中出现的特殊字符的数量。

或者至少,在发送到标准输出之前验证至少存在 1 个特殊字符。我更喜欢前者,但满足于后者。

这是我非常简单的该脚本的第 5 版。它没有验证,或 2 美元:

#!/bin/bash
cat /dev/urandom | tr -dc [=!=][=@=][=#=][=$=][=%=][=^=][:alnum:] | head -c $1

这工作得很好,它是一个足够安全的密码用法:

$ passgen 12
2ZuQacN9M@6!

但是,当然,它并不总是打印特殊字符,现在让我能够选择输出中存在多少特殊字符已成为一种痴迷。这并不像我想象的那么容易。

说得通?

顺便说一句,我不介意完全重写代码,我很想看到一些创造性的解决方案!

(顺便说一句:我尝试以各种方式将它通过管道传输到 egrep/grep 中,但无济于事,但我觉得这是一个可能的解决方案......)

谢谢凯文

4

5 回答 5

0

检查特殊字符很容易:

echo "$pass" | grep -q '[^a-zA-Z0-9]'

像这样:

while [ 1 ]; do
    pass=`cat /dev/urandom | tr -dc [=!=][=@=][=#=][=$=][=%=][=^=][:alnum:] | head -c $1`
    if echo "$pass" | grep -q '[^a-zA-Z0-9]'; then
        break;
    fi
done

最后:

normal=$(($1 - $2))
(
for ((i=1; i <= $normal; i++)); do
    cat /dev/urandom | tr -dc [:alnum:] | head -c 1
    echo
done
for ((i=1; i <= $2; i++)); do
    cat /dev/urandom | tr -dc [=!=][=@=][=#=][=$=][=%=][=^=] | head -c 1
    echo
done
) | shuf | sed -e :a -e '$!N;s/\n//;ta'
于 2011-07-08T20:47:38.833 回答
0

保持简单...... awk 中的解决方案,返回输入中“特殊字符”的数量

BEGIN {
    FS=""
    split("!@#$%^",special,"")
}
{
    split($0,array,"")
}
END {
    for (i in array) {
        for (s in special) {
            if (special[s] == array[i])
                tot=tot+1
        }
    }
    print tot
}

示例输出a2ZuQacN9M@6!

2

bash 中的类似方法:

#!/bin/bash
MyString=a2ZuQacN9M@6!
special=!@#$%^

i=0
while (( i++ < ${#MyString} ))
do
   char=$(expr substr "$MyString" $i 1)
   n=0
    while (( n++ < ${#special} ))
    do
       s=$(expr substr "$special" $n 1)
       if [[ $s == $char ]]
       then
           echo $s
       fi
    done
done
于 2011-07-08T22:26:53.533 回答
0

这个怎么样:

HASRANDOM=0
while [ $HASRANDOM -eq 0 ]; do
    PASS=`cat /dev/urandom | tr -dc [=!=][=@=][=#=][=$=][=%=][=^=][:alnum:] | head -c $1`
    if [[ "$PASS" =~ "[~\!@\#\$%^&\*\(\)\-\+\{\}\\\/=]{$2,}" ]]; then
        HASRANDOM=1
    fi  
done

echo $PASS

支持在输出中指定字符。您可以在正则表达式中添加字符,尽管即使在转义它们时我似乎也无法让方括号起作用。

您可能想要添加某种检查以确保它不会无限循环(尽管它对我来说从未走那么远,但我也没有要求太多特殊字符)

于 2011-07-08T21:13:21.810 回答
0

您还可以在参数扩展中使用字符类来删除字符串中的所有特殊字符,然后应用一些简单的 Bash 字符串长度数学来检查密码中是否存在最小(或确切)数量的特殊字符。

# example: delete all punctuation characters in string
str='a!@%3"'
echo "${str//[[:punct:]]/}"   

# ... taking Cfreak's approach we could write ...
(
set -- 12 3
strlen1=$1
strlen2=0
nchars=$2
special_chars='[=!=][=@=][=#=][=$=][=%=][=^=]'  

HASRANDOM=0
while [ $HASRANDOM -eq 0 ]; do
  PASS=`cat /dev/urandom | LC_ALL=C tr -dc "${special_chars}[:alnum:]" | head -c $1`
  PASS2="${PASS//[${special_chars}]/}"
  strlen2=${#PASS2}
  #if [[ $((strlen1 - strlen2)) -eq $nchars ]]; then   # set exact number of special chars
  if [[ $((strlen1 - strlen2)) -ge $nchars ]]; then   # set minimum number of special chars
    echo "$PASS"
    HASRANDOM=1
  fi
done
)
于 2011-07-09T19:02:50.323 回答
0

您可以使用以下方法计算特殊字符的数量:

number of characters - number of non special characters

尝试这个:

$ # define a string
$ string='abc!d$'                    
$ # extract non special chars to letters
$ letters=$(echo $string | tr -dc [:alnum:] )  
$ # substract the number on non special chars from total
$ echo $(( ${#string} - ${#letters} ))         
2

最后一部分$(( ... ))评估一个数学表达式。

于 2011-07-11T16:53:06.817 回答