【问题标题】:how do i verify presence of special characters in a bash password generator如何验证 bash 密码生成器中是否存在特殊字符
【发布时间】:2011-07-08 20:41:48
【问题描述】:

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

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

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

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

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

这很好用,而且它是一个足够安全的密码:

$ passgen 12
2ZuQacN9M@6!

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

有意义吗?

顺便说一句,我不介意对代码进行彻底的返工,我很想看到一些创造性的解决方案!

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

谢谢 凯文

【问题讨论】:

  • 看在上帝的份上……使用真正的编程语言来完成编程任务。
  • 原来的目标,在这变成怪物之前,是用 bash 写,然后用 ruby​​ 写,每个脚本运行 100 次,平均运行每个脚本所需的时间并比较.我喜欢真正的编程语言,但我喜欢 bash 的挑战
  • 另外,有时 bash 最适合这项工作。它又快又脏,而且可靠,也就是说 - 如果你知道你在做什么,我显然不知道:)
  • 我真的希望我可以降级@Kim Stebel 评论。就像有人说,嘿,我该如何更换 82 福特野马的变速箱,有人说,“买一辆新车,笨蛋” 是的,非常有帮助,谢谢
  • 除了使用不同的编程语言不花钱而且节省大量时间

标签: bash random passwords grep tr


【解决方案1】:

这个怎么样:

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

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

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

【讨论】:

  • 这确实很聪明,但实际上并没有完全解决问题。
  • 哦,我明白了。您想要正好 $2 的特殊字符?
  • 如果我这样运行: $ passgen_cfreak 12 2 XL0WEKGVPZP@ YPeW$HsB8Avj Ap2aSw64NcJW
  • 是的,我的错。我忘了取出我用来调试的回声。我修好了它。如果您想要 $2 特殊字符,请在 $2 之后取出逗号
  • 该死的 cmets... 输出是 "passgen_cfreak 12 2" 之后的字符串,你看到第三个不包含特殊字符了吗?
【解决方案2】:

检查特殊字符很容易:

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'

【讨论】:

  • 我喜欢你用这个去哪里,但这不起作用。我正在寻找至少 1 个特殊字符的存在。这不是吗? (顺便说一句,我没有记下你的答案)
【解决方案3】:

保持简单...在 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

【讨论】:

    【解决方案4】:

    您还可以在参数扩展中使用字符类来删除字符串中的所有特殊字符,然后应用一些简单的 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
    )
    

    【讨论】:

      【解决方案5】:

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

      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
      

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

      【讨论】:

        猜你喜欢
        • 2019-09-03
        • 2020-10-05
        • 2021-10-12
        • 1970-01-01
        • 2011-09-06
        • 1970-01-01
        • 2017-12-27
        • 2020-10-16
        • 1970-01-01
        相关资源
        最近更新 更多