Amarghosh
Amarghosh

Reputation: 59451

RegEx to make sure that the string contains at least one lower case char, upper case char, digit and symbol

What is the regex to make sure that a given string contains at least one character from each of the following categories.

I know the patterns for individual sets namely [a-z], [A-Z], \d and _|[^\w] (I got them correct, didn't I?).

But how do I combine them to make sure that the string contains all of these in any order?

Upvotes: 230

Views: 299810

Answers (4)

Ensei_Tankado
Ensei_Tankado

Reputation: 159

Bart Kiers solution is good but it misses rejecting strings having spaces and accepting strings having underscore (_) as a symbol.

Improving on the Bart Kiers solution, here's the regex:

(?=.*\d)(?=.*[a-z])(?=.*[A-Z])((?=.*\W)|(?=.*_))^[^ ]+$

A short explanation:

(?=.*[a-z])        // use positive look ahead to see if at least one lower case letter exists
(?=.*[A-Z])        // use positive look ahead to see if at least one upper case letter exists
(?=.*\d)           // use positive look ahead to see if at least one digit exists
(?=.*\W)           // use positive look ahead to see if at least one non-word character exists
(?=.*_)           // use positive look ahead to see if at least one underscore exists
|           // The Logical OR operator
^[^ ]+$           // Reject the strings having spaces in them.

Side note: You can try test cases on a regex expression here.

Upvotes: 15

Bart Kiers
Bart Kiers

Reputation: 170148

If you need one single regex, try:

(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*\W)

A short explanation:

(?=.*[a-z])        // use positive look ahead to see if at least one lower case letter exists
(?=.*[A-Z])        // use positive look ahead to see if at least one upper case letter exists
(?=.*\d)           // use positive look ahead to see if at least one digit exists
(?=.*\W)           // use positive look ahead to see if at least one non-word character exists

And I agree with SilentGhost, \W might be a bit broad. I'd replace it with a character set like this: [-+_!@#$%^&*.,?] (feel free to add more of course!)

Upvotes: 469

Juan Furattini
Juan Furattini

Reputation: 803

Bart Kiers, your regex has a couple issues. The best way to do that is this:

(.*[a-z].*)       // For lower cases
(.*[A-Z].*)       // For upper cases
(.*\d.*)          // For digits
(.*\W.*)          // For symbols (non-word characters)

In this way you are searching no matter if at the beginning, at the end or at the middle. In your have I have a lot of troubles with complex passwords.

Upvotes: 45

SilentGhost
SilentGhost

Reputation: 319551

You can match those three groups separately, and make sure that they all present. Also, [^\w] seems a bit too broad, but if that's what you want you might want to replace it with \W.

Upvotes: 6

Related Questions