I am currently writing a small script that checks the contents of each string.
I was wondering what the REGEX would be to make sure that a string has a letter (upper or lower), a digit, and a special character?
Here is what I know so far (whcih isn't much):
if(preg_match('/^[a-zA-Z0-9]+$/i', $string)):
Help would be great!
Thank You!
The easiest (and probably best) way is to do three separate checks with preg_match
:
$containsLetter = preg_match('/[a-zA-Z]/', $string);
$containsDigit = preg_match('/\d/', $string);
$containsSpecial = preg_match('/[^a-zA-Z\d]/', $string);
// $containsAll = $containsLetter && $containsDigit && $containsSpecial
You can use positive lookahead to create a single regex:
$strongPassword = preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$%^&]).*$/');
// special characters ^^^^
I have found great answer here with explanation to make sure that a given string contains at least one character from each of the following categories.
Lowercase character,
Uppercase character,
Digit,
Symbol
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$
A short explanation:
^
// the start of the string
(?=.*[a-z])
// use positive look ahead to see if at least one lower case letter exists
(?=.*[A-Z])
// use positive look ahead to see if at least one upper case letter exists
(?=.*\d)
// use positive look ahead to see if at least one digit exists
(?=.*[_\W])
// use positive look ahead to see if at least one underscore or non-word character exists
.+
// gobble up the entire string
$
// the end of the string
Hope that help you.
It may be best to use 3 distinct regexs to do this, since you would need to match 6 different possibilities, depending on where your special characters are in your string. But if you want to do it in one regex, and your special characters are, say, [+?@], it is possible:
$string = "abc@123";
$regex = "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$%^&]).*$/"
if (preg_match($regex, $string)) {
// special characters
}
A letter is \pL
, a number is \pN
and a special char is [what you want]
, here I assume it is not a letter and not a number, so the regex looks like:
/^(?=.*?\pL)(?=.*?\pN)(?=.*[^\pL\pN])/
False (chosen answer above - Thanks!) had the a pretty easy way to wrap your head around it (if you aren't too familiar with regex) and come up with what works for you.
I just put this in to elaborate a bit:
(you can paste it at http://phptester.net/index.php?lang=en to work with it)
<?php
$pass="abc1A";
$ucl = preg_match('/[A-Z]/', $pass); // Uppercase Letter
$lcl = preg_match('/[a-z]/', $pass); // Lowercase Letter
$dig = preg_match('/\d/', $pass); // Numeral
$nos = preg_match('/\W/', $pass); // Non-alpha/num characters (allows underscore)
if($ucl) {
echo "Contains upper case!<br>";
}
if($lcl) {
echo "Contains lower case!<br>";
}
if($dig) {
echo "Contains a numeral!<br>";
}
// I negated this if you want to dis-allow non-alphas/num:
if(!$nos) {
echo "Contains no Symbols!<br>";
}
if ($ucl && $lcl && $dig && !$nos) { // Negated on $nos here as well
echo "<br>All Four Pass!!!";
} else {
echo "<br>Failure...";
}
?>