2011-07-08 25 views
1

假設是一個簡單的bash腳本,但變成了怪物。這是第5次嘗試。你甚至不想看到第三行的怪物是#4 .. :)我如何驗證特殊字符在bash密碼生成器中的存在

下面是我想要做的:腳本生成一個隨機密碼,其中$ 1 =密碼長度,$ 2 =特殊數量字符出現在輸出中。

或者至少在發送到標準輸出前驗證至少存在1個特殊字符。我寧願選擇前者,但選擇後者。

這是我非常簡單的第5版本的腳本。它沒有驗證,或$ 2:

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

這一切正常,這是與使用足夠安全的口令:

$ passgen 12 
[email protected]! 

但是,當然,並不總是打印的特殊字符,現在我已經能夠選擇輸出中有多少特殊字符了。這並不像我想象的那麼容易。

有意義嗎?順便說一下,我不介意代碼的完整返工,我很樂意看到一些有創意的解決方案!

(順便說一句:我試着管成以各種方式的egrep/grep的,沒有用,但我有一種感覺,是一種可能的解決方案...)

感謝 凱文

+2

對上帝的愛....使用一個真正的編程語言的編程任務。 –

+0

我喜歡他的做法:) –

+0

以及原來的目標,在此之前變成了一個怪物,是把它寫在bash,那麼它在紅寶石寫,運行每個腳本100倍,平均需要運行每個和比較的時間。我喜歡真正的編程語言,但我也喜歡bash – Kevin

回答

0

檢查特殊字符很簡單:

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

像這樣:

while [ 1 ]; do 
    pass=`cat /dev/urandom | tr -dc [=!=][[email protected]=][=#=][=$=][=%=][=^=][: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 [=!=][[email protected]=][=#=][=$=][=%=][=^=] | head -c 1 
    echo 
done 
) | shuf | sed -e :a -e '$!N;s/\n//;ta' 
+0

我喜歡你的這個會做到這一點,但也不至於工作。我正在驗證特殊字符的存在,至少是1.這不是這樣嗎? (我沒有標記你的答案順便說一句) – Kevin

+1

確實在這裏工作。還增加了完整的解決方案。 –

+1

至少給予好評它,所以它不是-1 .. :) –

0

如何:

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

echo $PASS 

支持輸出指定的字符。您可以在正則表達式中添加字符,儘管我似乎無法使方括號工作,即使在轉義它們時也是如此。

你可能會想添加某種檢查,以確保它不會無限循環下去(儘管它從來沒有去那麼遠的我,但我沒有問太多的特殊字符要麼)

+0

這真是聰明,但它實際上並沒有完全解決問題。 – Kevin

+0

@凱文 - 它以什麼方式解決不了問題? – Cfreak

+0

哦,我明白了。你想要2美元的特殊字符? – Cfreak

0

保持它很簡單...解決方案在awk中,在輸入返回 「特殊字符」 數

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

例輸出[email protected]!

2 

在bash類似的方法:

#!/bin/bash 
[email protected]! 
[email protected]#$%^ 

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 
0

您也可以使用參數展開中的字符類刪除字符串中的所有特殊字符,然後應用一些簡單的Bash字符串長度數學來檢查是否存在最小(或確切)數量的密碼中的特殊字符。

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

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

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 
) 
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 

最後一部分$((...))評估數學表達式。