Bash on * nix (109)
while ! grep -Pq [A-Z].*[a-z].*[0-9].*[\\W_]<<<$a$a$a$a
do a=`tr -dc !-~</dev/urandom|head -c15`
done
echo $a
Pour fonctionner correctement, vous $a
ne devez pas définir un mot de passe valide mais non aléatoire à l’avance. Si vous voulez inclure a=
et séparer une ligne, cela fait trois caractères de plus, mais cela vous permet d’exécuter la chose à plusieurs reprises. Vous pouvez évidemment aussi remplacer toutes les nouvelles lignes par;
afin que vous ayez une ligne que vous pouvez exécuter aussi souvent que vous le souhaitez.
De plus, vous devez avoir défini LC_ALL=C
ou non des variables d’environnement spécifiques aux paramètres régionaux ( LANG
etLC_CTYPE
en particulier) , car les plages de caractères dépendent du fait que l’ordre de classement est égal à l’ordre ascii.
/dev/urandom
est la source d'octets aléatoires. !-~
est la plage de tous les caractères autorisés, comme spécifié dans la question. tr -dc
supprime tous les caractères non listés dans son argument suivant. head
prend 15 des caractères restants. grep
vérifie si chacun des types requis apparaît au moins une fois. Son entrée consiste en quatre copies du candidat. L'ordre des symboles n'a donc pas d'importance. Tous les mots de passe possibles ont donc une chance d'être sélectionnés. La -q
grep sortie de supprime.
Pour des raisons inconnues, /dev/random
au lieu de /dev/urandom
prend des âges. Il semble que l'entropie se soit épuisée assez rapidement. Si vous cd
en /dev
, vous pouvez éviter certains plus d' octets, mais qui se sent un peu comme la tricherie.
Python 2 (138)
import re,random
a=''
while not re.search('[A-Z].*[a-z].*[0-9].*[\W_]',a*4):
a=''.join(random.sample(map(chr,range(33,127))*15,15))
print a
Pour rendre le code lisible, j'ai ajouté une nouvelle ligne et une indentation après la boucle, ce qui n'est pas nécessaire et que je n'ai pas compté.
C'est essentiellement la même idée que dans la version bash. La source aléatoire est ici random.sample
, qui ne répétera pas les éléments. Pour contrer ce fait, nous utilisons 15 exemplaires de la liste des lettres autorisées. De cette façon, chaque combinaison peut encore se produire, bien que celles avec des lettres répétées se produisent moins souvent. Mais je décide de considérer cela comme une fonctionnalité et non comme un bug, car la question n'exigeait pas une probabilité égale pour toutes les permutations, mais seulement la possibilité.
Python 3 (145)
import re,random
a=''
while not re.search('[A-Z].*[a-z].*[0-9].*[\W_]',a*4):
a=''.join(random.sample(list(map(chr,range(33,127)))*15,15))
print(a)
Une nouvelle ligne et un retrait à nouveau ne comptent pas. Hormis une surcharge de syntaxe spécifique à Python-3, il s'agit de la même solution que pour Python 2.
JavaScript (161)
a=[];for(i=33;i<127;)a.push(s=String.fromCharCode(i++));
while(!/[A-Z].*[a-z].*[0-9].*[\W_]/.test(s+s+s+s))
for(i=0,s="";i<15;++i)s+=a[Math.random()*94|0];alert(s)
J'ai ajouté les nouvelles lignes pour plus de lisibilité, mais je ne les ai pas comptées.
R (114)
s<-""
while(!grepl("[A-Z].*[a-z].*[0-9].*(\\W|_)",paste(rep(s,4),collapse="")))
s<-intToUtf8(sample(33:126,15,T))
s
Le saut de ligne et l'indentation dans la boucle ont été ajoutés mais non comptés. Si vous en avez envie, vous pouvez à nouveau déplacer ceci sur une ;
ligne à simple séparation.