1

単純な bash スクリプトであるはずが、怪物になってしまいました。5回目の挑戦です。試み #4 であった 30 行の怪物も見たくありません.. :)

私がやりたいことは次のとおりです。スクリプトは、$1=パスワードの長さ、および $2=出力に存在する特殊文字の量で、ランダムなパスワードを生成します。

または、少なくとも、標準出力に送信する前に、少なくとも 1 つの特殊文字が存在することを確認してください。私は前者を好むが、後者に落ち着く。

これが、このスクリプトの非常に単純な 5 番目のバージョンです。検証なし、または $2:

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

これは問題なく機能し、Usage で十分に安全なパスワードです。

$ passgen 12
2ZuQacN9M@6!

しかし、もちろん、常に特殊文字が出力されるとは限りません。出力に含まれる特殊文字の数を選択できるようにすることは、私にとって強迫観念になっています。思ったほど簡単ではありません。

わかる?

ところで、私はコードを完全に作り直すことは気にしません。いくつかの創造的な解決策を見ることに非常に興味があります!

(ちなみに、さまざまな方法で egrep/grep にパイプしようとしましたが、役に立ちませんでしたが、解決策の可能性があると感じています...)

ありがとうケビン

4

5 に答える 5

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

特殊文字のチェックは簡単です:

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

次のようなものを使用して、特殊文字の数を数えることができます。

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 に答える
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

シンプルにしてください...入力の「特殊文字」の数を返す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 に答える