Algumas coisas:
-
Usar read
sem -r
dificulta ter \
na senha.
-
Não citar as expressões regulares fará com que o shell as trate como padrões de globbing e elas se expandirão para nomes de arquivos.
-
A variável $?
manterá apenas o status de saída do último grep
.
Considere o seguinte script bash
:
#!/bin/bash
read -r -p "password:" -s password
if (( ${#password} < 8 )); then
echo "Passwords need 8 or more characters"
exit 1
fi
has_upcase=0
has_locase=0
has_digit=0
has_other=0
case "$password" in
*[[:upper:]]*) has_upcase=1 ;;&
*[[:lower:]]*) has_locase=1 ;;&
*[[:digit:]]*) has_digit=1 ;;&
*[^[:alnum:]]*) has_other=1 ;;
esac
if (( !has_upcase )); then
echo "Make sure you password has at least one upper-case letter"
elif (( !has_locase )); then
echo "Make sure your password has at least one lower-case letter"
elif (( !has_digit )); then
echo "Make sure your password has at least one digit"
elif (( !has_other )); then
echo "Make sure your password has at least non-alphanumeric character"
else
echo "Your password is ok"
fi
Eu tomei a liberdade de adicionar um requisito "não alfanumérico" ao teste.
O read
de bash
é capaz de fornecer ao usuário um prompt e ler enquanto não está ecoando o que é digitado.
A instrução case
verifica se a senha inserida contém pelo menos um caractere em maiúsculas, uma minúscula, um numérico e um não alfanumérico (usando As classes de caracteres POSIX ). O funky olhando ;;&
no final de cada linha significa "continue testando o próximo padrão com esta string".
Para obter uma variante sh
do POSIX, substitua o read
por
stty -echo
printf "password: "
read -r password
stty echo
printf "\n"
E a declaração case
com algo como
case "$password" in *[[:upper:]]*) has_upcase=1 ;; esac
case "$password" in *[[:lower:]]*) has_locase=1 ;; esac
case "$password" in *[[:digit:]]*) has_digit=1 ;; esac
case "$password" in *[^[:alnum:]]*) has_other=1 ;; esac
O resto ainda deve ser POSIX.