how do i verify presence of special characters in a bash password generator
Supposed to be a simple bash script, but turned into a monster. This is the 5th try. You don't even want to see the 30 line monstrosity that was attempt #4.. :)
Here's what I want to do: Script generates a random password, with $1=password length, and $2=amount of special characters present in the output.
Or at least, verify before sending to standard out, that at least 1 special character exists. I would prefer the former, but settle for the latter.
Here's my very simple 5th version of this script. It has no verification, or $2:
#!/bin/bash
cat /dev/urandom | tr -dc [=!=][=@=][=#=][=$=][=%=][=^=][:alnum:] | head -c $1
This works just fine, and it's a sufficiently secure password with Usage:
$ passgen 12
2ZuQacN9M@6!
But it, of course, doesn't always print special characters, and it's become an obsession for me now to be able to allow selection of how many special characters are present in th开发者_如何学Ce output. It's not as easy as I thought.
Make sense?
By the way, I don't mind a complete rework of the code, I'd be very interested to see some creative solutions!
(By the way: I've tried to pipe it into egrep/grep in various ways, to no avail, but I have a feeling that is a possible solution...)
Thanks Kevin
How about this:
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
Supports specifying characters in the output. You could add characters in the regex though I couldn't seem to get square brackets to work even when escaping them.
You probably would want to add some kind of check to make sure it doesn't loop infinitely (though it never went that far for me but I didn't ask for too many special characters either)
Checking for special characters is easy:
echo "$pass" | grep -q '[^a-zA-Z0-9]'
Like this:
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
And finally:
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'
Keep it simple... Solution in awk that return the number of "special characters" in input
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
}
Example output for a2ZuQacN9M@6!
is
2
Similar approach in 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
You may also use a character class in parameter expansion to delete all special chars in a string and then apply some simple Bash string length math to check if there was a minimum (or exact) number of special chars in the password.
# 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
)
You can count the number of special chars using something like:
number of characters - number of non special characters
Try this:
$ # 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
The last part $(( ... ))
evaluate a mathematical expression.
精彩评论