The best way to match at least three of the four regular expression requirements

There are 4 requirements in a password strategy. It must contain any three of the following

  • lower case.
  • uppercase.
  • Numerical.
  • special character.

The following regular expression will match all cases

^(?=.*\d)(?=.*[az])(?=.*[AZ])(?=.*[^a-zA-Z0-9]).{4,8}$ 

I know I can use '|' however, declare all combinations that will cause a long regular expression of the dinner. What is the best way to replace '|' so that he can check if the input contains any of the three conditions in combination?

+6
source share
2 answers

If you use PCRE, the following might suit your needs (formatted for readability):

 ^(?: ((?=.*\d))((?=.*[az]))((?=.*[AZ]))((?=.*[^a-zA-Z0-9]))| (?1) (?2) (?3) | (?1) (?2) (?4) | (?1) (?3) (?4) | (?2) (?3) (?4) ).{4,8}$ 

Regular expression visualization

One lining:

 ^(?:((?=.*\d))((?=.*[az]))((?=.*[AZ]))((?=.*[^a-zA-Z0-9]))|(?1)(?2)(?3)|(?1)(?2)(?4)|(?1)(?3)(?4)|(?2)(?3)(?4)).{4,8}$ 

Demo on Debuggex


JavaScript regex flavor does not support recursion (it practically does not support many things). It is better to use 4 different regular expressions, for example:

 var validate = function(input) { var regexes = [ "[AZ]", "[az]", "[0-9]", "[^a-zA-Z0-9]" ]; var count = 0; for (var i = 0, n = regexes.length; i < n; i++) { if (input.match(regexes[i])) { count++; } } return count >=3 && input.match("^.{4,8}$"); }; 
+3
source

Of course, here is a method that uses a small modification of the same regular expression, but with a short short code authoring.

 ^(?=(\D*\d)|)(?=([^az]*[az])|)(?=([^AZ]*[AZ])|)(?=([a-zA-Z0-9]*[^a-zA-Z0-9])|).{4,8}$ 

Here you have five capture groups - check to see if at least 3 of them are null. A null capture group effectively indicates that the alternative within the lookahead is mapped, and the capture group on the left cannot be mapped.

For example, in PHP:

 preg_match("/^(?=(\\D*\\d)|)(?=([^az]*[az])|)(?=([^AZ]*[AZ])|)(?=([a-zA-Z0-9]*[^a-zA-Z0-9])|).{4,8}$/", $str, $matches); $count = -1; // Because the zero-eth element is never null. foreach ($matches as $element) { if ( !empty($element)) { $count += 1; } } if ($count >= 3) { // ... } 

Or Java:

 Matcher matcher = Pattern.compile(...).matcher(string); int count = 0; if (matcher.matches()) for (int i = 1; i < 5; i++) if (null != matcher.group(i)) count++; if (count >= 3) // ... 
+1
source

Source: https://habr.com/ru/post/978320/


All Articles