Hello Bryan,
Even though this expression works, I found it hard to read and probably hard
to maintain, so I've been experimenting with Balanced groups to see if there
was a more elegant solution to this problem. I came up with this expressionL
^(?=(?<valid>.*\W)?)(?=(?<valid>.*[0-9])?)(?=(?<valid>.*[a-z])?).{8,}(?<-valid>){2}$
I'll try to explain how it works:
First notice that the expression looks very similar to what we had before.
If you haven't worked with balancing groups before, which most people haven't
all you need to know is that you can use them to count occurances. Origially
so that you know how many times you for example opened a ( and how many times
you closed one. Instead of ensuring that something that was opened is also
closed I use it here to check if there is at least a specific number of matches
left.
In the above case there are 3 checks done:
- Any special character (\W)
- Any numeric character ([0-9])
- Any lowercase alfanumeric character ([a-z])
As you probably also noted, I made the each of the look aheads optional.
They would otherwise all be enforced, which wouldn't help. Then I used the
above mentioned balancing groups to see how many of these groups actually
did match something. To do so I named each of the tests with (?<valid>....).
You can substract (?-<valid>...) and add (?<valid>....) values matched to
a balancing group. If you try to substract a value when there is no matching
addition, the regex will fail.
With his knowledge we can finish the 2 out of 3 rule we were trying to enforce.
If we substract the least amount of matches we require from the balancing
group without error, the regex will match. If there are not enough matches
left, the regex will fail automatically.
In this example I require 2 out of 3, so 2 substractions must match:
(?<-valid>){2}
Which solves out problem.
Because this all works with named matches you could use this to make pretty
complex rules to which a password must comply. You can also enforce certain
rules at all times, yet have other rules be mutually allowed if at least
x of these optional rules match.
There is one downside though. Clientside javascript does not support balancing
groups, and therefore you can use this regex only at the server side.
it would be nice if the validation controls would allow you to specifiy a
rule on both the client and the server side so that you can do a global match
on the client, and a more thourough one at the server. I think I'll create
my own regex validator to do just that in my next .NET project.
Kind regards,
--
Jesse Houwing
jesse.houwing at sogeti.nl
Perfect..
Thanks a bunch Misbah! I appreciate it.
oops, sorry I misinterpreted your question
try
^((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.{8,})|(?=.*[a-z])(?=.*[A-Z])(?=.*
[@#\$%\^&\+=])(?=.{8,})|(?=.*\d)(?=.*[a-z])(?=.*[@#\$%\^&\+=])(?=.{8,
})|(?=.*\d)(?=.*[A-Z])(?=.*[@#\$%\^&\+=])(?=.{8,})).*$
--
Misbah Arefin
Thanks Misbah
That seems to make them all required.
I need at least 3 of the 4 to be met.
message
try
^.*(?=.{8,})((?=.*\d)(?=.*[@#\$%\^&\+=]))(?=.*[a-z])(?=.*[A-Z]).*$