I'm creating in PHP a $pattern for a preg_match($pattern, $password)
function, and it should be a regexp that defines a string made this way:
$str_lenght
long AND$num_capitals
capital letters AND$num_numerals
numbers AND$num_symbols
from this range: !@#$%^&*()-+?How can I do it?
You can build your regex this way using lookaheads:
$re = '/(?=(.*?[A-Z]){' . $num_capitals . '})(?=(.*?[0-9]){' . $num_numerals .
'})(?=(.*?[!@#$%^&*()+?-]){' . $num_symbols . '}).{' . $str_lenght . ',}/';
@anubhava greatly destroyed my answer, but I'll leave it for an alternative approach
.
matches all characters, {5,}
repeats it 5+ times. However, since we aren't making one long expression, I would still use the faster strlen()
. Demo:
.{5,}
For the rest, I would match a character class and use preg_match_all()
which will return the total number of matches (may be 0).
Here are the 3 character classes you want:
[A-Z]
[0-9] OR \d (\d will match other numeric characters, like Arabic, etc.)
[!@#$%^&*()+?-]
An example implementation:
$count = preg_match_all('/[A-Z]/', 'FOObar', $matches);
// $count = 3;
Please note in the final character class ([!@#$%^&*()+?-]
), ^
must not come first and -
must not be in the middle..otherwise you'll need to escape them with \
because they have special meanings.
Try this
$strRegex = '/((?=.*\d).{'.$num_numerals.'})((?=.*[a-z]).{'.$num_lower.'})((?=.*[A-Z]).{'$num_upper'})((?=.*[@#$%]).{'.$num_symbols.'})/';
Or
$strRegex = '/((?=.*\d).{'.$num_numerals.'})((?=.*[a-z]).{1,'.$num_lower.'})((?=.*[A-Z]).{'$num_upper'})((?=.*[@#$%]).{'.$num_symbols.'})/';
And based on $num_lower you can limit nuber of characters allowed in the password. And the pass will accept lower case from 1 to $num_lower