tags:

views:

477

answers:

5

I'm looking for a rather specific regex and I almost have it but not quite.

I want a regex that will require at least 5 charactors, where at least one of those characters is either a numeric value or a nonalphanumeric character.

This is what I have so far:

^(?=.*[\d]|[!@#$%\^*()_\-+=\[{\]};:|\./])(?=.*[a-z]).{5,20}$

So the problem is the "or" part. It will allow non-alphanumeric values, but still requires at least one numeric value. You can see that I have the or operator "|" between my require numerics and the non-alphanumeric, but that doesn't seem to work.

Any suggestions would be great.

A: 

How about like this?

^.*?[\d!@#$%\^*()_\-+=\[{\]};:|\./].*$

For the length 5,20 Please use normal strlen function

S.Mark
That doesn't actually work, as if you want a non-alphanumeric or numeric character at the start or end, it will fail. However, you did get me on the right track.
Chris Nicol
Have you really tested? It should works for non-alphanumeric or numeric character at the start or end too.
S.Mark
A: 

Is it really necessary to stuff everything in a giant regex? Just use program logic (5 ≤ length(s) ≤ 20) ∧ (/[[:digit:]]/ ∨ /[^[:alpha:]]/). Far more readable syntactically and semantically, I think.

Cirno de Bergerac
I'm using ASP.NET membership all over the place, would need to go back and implement that logic in multiple places along with exceptions etc. It's easier to use Regex in the Membership config. Regex has it's place just like all other programming techniques.
Chris Nicol
+1  A: 

Perhaps this may work for you:

^.*[\d\W]+.*$

And use some code like this to check string size:

if(str.len >= 5 && str.len =< 20 && regex.ismatch(str, "^.*[\d\W]+.*$")) { ... }
Bob
I need it all in a regex for my current problem.
Chris Nicol
A: 

Pretty simple solution, once S.Mark got me on the right track, just needed to merge my numeric and non-alphanumeric pieces as one.

Here's the final regex for anyone that's interested:

^(?=.*[\d!@#$%\^*()_\-+=\[{\]};:|\./])(?=.*[a-z]).{5,20}$

This will allow any password between 5 and 20 characters and requires at least one letter and one numeric and/or one non-alphanumeric character.

Chris Nicol
+5  A: 

Try:

^(?=.*(\d|\W)).{5,20}$

A short explanation:

^                         # match the beginning of the input
(?=                       # start positive look ahead
  .*                      #   match any character except line breaks and repeat it zero or more times
  (                       #   start capture group 1
    \d                    #     match a digit: [0-9]
    |                     #     OR
    \W                    #     match a non-word character: [^\w]
  )                       #   end capture group 1
)                         # end positive look ahead
.{5,20}                   # match any character except line breaks and repeat it between 5 and 20 times
$                         # match the end of the input
Bart Kiers
afraid not ... that doesn't require you to have a number or non-alphanumeric character
Chris Nicol
Yes it does. I guess you didn't test it properly? The look ahead requires the string to contain at least one digit or non-word.
Bart Kiers
... and if you meant *"a number **and** non-alphanumeric character"* instead, then this will do the trick: `^(?=.*\d)(?=.*\W).{5,20}$`
Bart Kiers