tags:

views:

438

answers:

5

I'm looking for a regex that will check if the string only consists of the letters a-z, numbers, underscore (_) and hyphen (-). I have tried this, but it does not work:

if (!preg_match('/^a-zA-Z0-9_-$/', $string)) {
  $reg_Error[] = 2;
}

Also, can I check the length with regex? If not, I will just do it with PHP.

+1  A: 

The regex should be: '^[\w\d-]+$'

Ed L
To explain that: '-' is a special character inside square brackets *unless* it is the first or last character in the brackets.
Colin Fine
`a-zA-Z_` can be replaced by `\w`, `0-9` can be replaced by `\d`
RaYell
`a-zA-Z0-9_` can be replaced by `\w` only.
Andrea Ambu
+2  A: 

Shortest one:

/^[\w-]+$/

seize
Even shorter: `/^[\w-]+$/`
RaYell
And where's the underscore??
seize
The underscore is part of `\w`.
Michael Myers
\w includes _. Note that in other locales, \w can include accented characters.
OIS
Edited to be the shortest...
seize
-1 Correctness is better than shortness.
Gumbo
And isn't it correct??
seize
+6  A: 

You have to put your regex /^a-zA-Z0-9_-$/ in a character class /[...]/.
It means you can match any character in the character class. You should also specify a quantifier, because /^[a-zA-Z0-9_-]$/ will match only one character.

Examples:
/^[a-zA-Z0-9_-]+$/ with the + sign you match it one or more time
/^[a-zA-Z0-9_-]{1,}$/ the same as above
/^[a-zA-Z0-9_-]{10,20}$/ between 10 and 20 character long.
/^[a-zA-Z0-9_-]{15}$/ it has to be exactly 15 characters long. You can use it to check the sting length.

You can also use the following keyword to make your regex easy to read:
/^[\w-]+$/ which matches a word character (including underscore, letters and digits) or a dash, one or more time.

Andrea Ambu
+1  A: 

The answers so far correctly explain the character class /^[A-Za-z0-9_-]+$/

You can check the length. + means "one or more of the preceding", * means zero or more of the preceding" and {2,4} means "between 2 and 4 of the preceding".

You can't specify the length has to be a prime, though. Specifying that the length has to be even is possible but non-trivial: /^(xx){1,3}$/ matches xx, xxxx or xxxxxx. The count here refers to the number of pairs, not the number of x'es

MSalters
A: 

I would use this one:

/^[a-z_\-\d]+$/i

As to why I'm not using \w, the following quote, taken from PHP PCRE Pattern Reference, should explain why you shouldn't be using \w in this situation:

A "word" character is any letter or digit or the underscore character, that is, any character which can be part of a Perl "word". The definition of letters and digits is controlled by PCRE's character tables, and may vary if locale-specific matching is taking place. For example, in the "fr" (French) locale, some character codes greater than 128 are used for accented letters, and these are matched by \w.

That behavior is not desirable in this case, so unless you want to worry about locale, use straight character classes instead of the \w shorthand.

If you want to specify a minimum length (for example 3):

/^[a-z_\-\d]{3,}$/i

If you want to specify both a minimum and maximum length (for example 2 and 5):

/^[a-z_\-\d]{2,5}$/i
Andrew Moore