I have a requirement for password rules. Following are the rules.
The password must follow the following guidelines:
This is, if you want an elegant regex, as close as you can get
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&'])[^ ]{8,}$
The basic idea is to use a technique called "positive lookahead" :
(?=.*PutHereWhatYouWantToAllow)
Your extra requirement 3 out of 4 is not easy to solve with regexes cause you cannot make them count basically. You could write out the necessary permutations of the above regex (tell me if it doesn't make sense) but that would make a very long regex. What you could do is write out the permutations in code so that the regex stays maintainable since you are not repeating the patterns literally.
I'll have a shot if I you tell me your language (C#?) cause it's a good challenge.
Update 1
Here is the regex that will match at least 3 of your requirements (4 is also allowed), just for the challenge of it. Don't use this in production but loop in the language with individual regexes as mentioned in the comments.
^((?=.[a-z].[A-Z].[\d])|(?=.[a-z].[\d].[A-Z])|(?=.[A-Z].[a-z].[\d])|(?=.[A-Z].[\d].[a-z])|(?=.[\d].[a-z].[A-Z])|(?=.[\d].[A-Z].[a-z])|(?=.[a-z].[A-Z].[!@#$%^&'])|(?=.[a-z].[!@#$%^&'].[A-Z])|(?=.[A-Z].[a-z].[!@#$%^&'])|(?=.[A-Z].[!@#$%^&'].[a-z])|(?=.[!@#$%^&'].[a-z].[A-Z])|(?=.[!@#$%^&'].[A-Z].[a-z])|(?=.[a-z].[\d].[!@#$%^&'])|(?=.[a-z].[!@#$%^&'].[\d])|(?=.[\d].[a-z].[!@#$%^&'])|(?=.[\d].[!@#$%^&'].[a-z])|(?=.[!@#$%^&'].[a-z].[\d])|(?=.[!@#$%^&'].[\d].[a-z])|(?=.[A-Z].[\d].[!@#$%^&'])|(?=.[A-Z].[!@#$%^&'].[\d])|(?=.[\d].[A-Z].[!@#$%^&'])|(?=.[\d].[!@#$%^&'].[A-Z])|(?=.[!@#$%^&'].[A-Z].[\d])|(?=.[!@#$%^&'].[\d].[A-Z]))[^ ]{8,}$
Update 2
This is the approach to take in java
From the comments I read that you are testing like the following
I don't think you are on the right track here. The lowercase will only report success if all characters are lowercase, and not just one. Same remark for the rest.
These are the 4 individual regexes of which at least 3 should report a match
[a-z]
[A-Z]
\d
[!@#$%^&']
Here is the test that the password should not contain a space
^[^ ]*$
The test for at least 8 characters
.{8,}
So I split the requirements and not combine them. This should make for more readable code especially if one starts with regexes.