tags:

views:

125

answers:

3

I want a regular expression to validate a nickname: 6 to 36 characters, it should contain at least one letter. Other allowed characters: 0-9 and underscores.

This is what I have now:

if(!preg_match('/^.*(?=\d{0,})(?=[a-zA-Z]{1,})(?=[a-zA-Z0-9_]{6,36}).*$/i', $value)){
 echo 'bad';
}
else{
 echo 'good';
}

This seems to work, but when a validate this strings for example:

11111111111a > is not valid, but it should aaaaaaa!aaaa > is valid, but it shouldn't

Any ideas to make this regexp better?

+4  A: 

I would actually split your task into two regex:

  1. to find out whether it's a valid word: /^\w{6,36}$/i
  2. to find out whether it contains a letter /[a-z]/i

I think it's much simpler this way.

SilentGhost
+2  A: 

Try this:

'/^(?=.*[a-z])\w{6,36}$/i'

Here are some of the problems with your original regex:

/^.*(?=\d{0,})(?=[a-zA-Z]{1,})(?=[a-zA-Z0-9_]{6,36}).*$/i
  • (?=\d{0,}): What is this for??? This is always true and doesn't do anything!
  • (?=[a-zA-Z]{1,}): You don't need the {1,} part, you just need to find one letter, and i flag also allows you to omit A-Z
  • /^.*: You're matching these outside of the lookaround; it should be inside
  • (?=[a-zA-Z0-9_]{6,36}).*$: this means that as long as there are between 6-36 \w characters, everything else in the rest of the string matches! The string can be 100 characters long mostly containing illegal characters and it will still match!
polygenelubricants
You can omit the `A-Z`, or the `i` flag.
Bart Kiers
Suggestion incorporated. Thanks.
polygenelubricants
A: 

You can do it easily using two calls to preg_match as:

if( preg_match('/^[a-z0-9_]{6,36}$/i',$input) && preg_match('/[a-z]/i',$input)) {
 // good
} else {
// bad
}
codaddict
A bit late: it's a duplicate of SilentGhost's answer.
Bart Kiers