views:

671

answers:

6

Hi,

Say I have a regex that checks for alphanumeric.

I now want to create another regex that checks for at least 1 number in the password. And I want to check if it has at least 1 non-alphanumeric character (somethign other than a letter or number).

Should I just call each one seperatley, and if one fails return false or is there a way to combine them into 1 call?

A: 

You add an | (or) operator into the regex e.g.

[0-9]|[A-Z]

James
`[A-Z0-9]` would work just as well.
Noldorin
True, however I always feel its nicer to use the | to split them up so it is clearer what is going on
James
Actually this statement wouldn't work because it is not implementing the required AND. This regexp fires if a capital letter OR a numerical is present. Requested has been "one or more digits AND one or more non-alphanumericals".
Don Johe
He already has the regexes, he wanted to know how to use 2 regexes in the one statement...
James
@James, that's faulty thinking on both counts. `[0-9]|[A-Z]` may seem clearer than `[0-9A-Z]` to you, but it's also much less efficient. (It won't matter in this case, but the difference can be dramatic.) And, as Don Johe said, you need to AND the regexes, not OR them. That usually calls for lookaheads: `(?=.*[0-9])(?=.*[A-Z])` etc. (This has been rehashed dozens of times; just search for "password regex".)
Alan Moore
I think I misunderstood the question then, I assumed he had 2 regexes and wanted to test if the string matched either or.
James
+3  A: 

Depends on exactly what criteria you're using, but it would probably be better to do a single pass through the string and set a number of flags based on what you've seen:

  • hasDigit
  • hasAlpha
  • hasSymbol
  • etc

Then use these at the end to decide if the password is complex enough.

Even Better:

As lexu suggests, using counts instead of flags would allow greater flexibility.

Draemon
I like the idea (and it answers the question asked!), but I would suggest counting Digits,Aplha,Symbol instead of setting a single flag each .. this enables the next step -> evaluating the PWD strength.
lexu
Very good point
Draemon
+1  A: 

You should use two calls. For a bit more advanced testing you can use The password meter. It is freely available for distribution under GPL.

Andrea Ambu
+1  A: 

I would compose small methods using &&:

internal bool HasDigit(string password) { .. }
internal bool HasNonAlpha(string password) { .. }

bool IsStrong(string password) {  
   return HasDigit(password) && HasNonAlpha(password);
}
dfa
+1  A: 

IMHO, it's a question of style whether to make one or two statements from it.

Why not check for it in any of the two orders that they may appear. (As regular expressions go, we don't have something like a counter for braces or parantheses, thus we have to honor the possible ordering of things.

That one might work for perl:

(\d.*[^[:alnum:]])|([^[:alnum:]].*\d)

Might be easier to read to make two statements from it, especially because then every semantical condition is only occurring once.

Don Johe
Hey, look: somebody actually answered the question. There ought to be more upvotes.
Jeremy Stein
Actually this is not strictly an answer (because it is not C#), but I think regexps everywhere are mostly perl-syntax. (At least you stumble upon "see perl regexp doc for details" every now and then.)
Don Johe
A: 

I think this is what you're looking for:

^.{6,}(?<=\d.*)(?<=[^a-zA-Z0-9].*)$

(will match a password with a minimum length of 6, with at least one digit and one non-alphanumerical character)

In code:

public bool PasswordOk(string pwd) 
{
    return Regex.IsMatch(pwd,@"^.{6,}(?<=\d.*)(?<=[^a-zA-Z0-9].*)$");
}
Philippe Leybaert
I thought it was a bad idea to have an infinite repetition inside a look-behind. I suppose it's not a big deal for a small sample.
Jeremy Stein
A password is a small sample, so I think it's a perfectly acceptable solution for easy password validation.
Philippe Leybaert