正则表达式,定义一个具有不同数量的三个不同字符组的字符串

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:

  • at least $str_lenght long AND
  • that has at least $num_capitals capital letters AND
  • that has at least $num_numerals numbers AND
  • that has at least $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