tags:

views:

74

answers:

4

I'm still kinda new to using Regular Expressions, so here's my plight. I have some rules for acceptable usernames and I'm trying to make an expression for them.

Here they are:

  • 1-15 Characters
  • a-z, A-Z, 0-9, and spaces are acceptable
  • Must begin with a-z or A-Z
  • Cannot end in a space
  • Cannot contain two spaces in a row

This is as far as I've gotten with it.

/^[a-zA-Z]{1}([a-zA-Z0-9]|\s(?!\s)){0,14}[^\s]$/

It works, for the most part, but doesn't match a single character such as "a".

Can anyone help me out here? I'm using PCRE in PHP if that makes any difference.

+4  A: 

Try this:

/^(?=.{1,15}$)[a-zA-Z][a-zA-Z0-9]*(?: [a-zA-Z0-9]+)*$/

The look-ahead assertion (?=.{1,15}$) checks the length and the rest checks the structure:

  • [a-zA-Z] ensures that the first character is an alphabetic character;
  • [a-zA-Z0-9]* allows any number of following alphanumeric characters;
  • (?: [a-zA-Z0-9]+)* allows any number of sequences of a single space (not \s that allows any whitespace character) that must be followed by at least one alphanumeric character (see PCRE subpatterns for the syntax of (?:…)).

You could also remove the look-ahead assertion and check the length with strlen.

Gumbo
@Bart K.: Thanks. :)
Gumbo
You're a lifesaver! Could you also explain a little more about how it works? I'm still learning and none of that really make a lot of sense to me.
dan
A: 

The main problem of your regexp is that it needs at least two characters two have a match :

  • one for the [a-zA-Z]{1} part
  • one for the [^\s] part

Beside this problem, I see some parts of your regexp that could be improved :

  • The [^\s] class will match any character, except spaces : a dot or semi-colon will be accepted, try to use the [a-zA-Z0-9] class here to ensure the character is a correct one.
  • You can delete the {1} part at the beginning, as the regexp will match exactly one character by default
Thibault Falise
This will match strings with a space at the end
NullUserException
Now it also matches strings ending with a whitespace character.
Gumbo
Thibault Falise
A: 

Your problem is the [^\s] at the end, it forces you to have at least one character there after matching the previous part of the regex. Try this instead:

/^[a-zA-Z]([a-zA-Z0-9]|\s(?!\s)){0,14}(?<!\s)$/

The (?<!\s) there is a lookbehind assertion. Also note that \s is a character class that includes tabs, newlines and whitespaces. You could replace that with a whitespace if needed.

NullUserException
A: 

make everything after your first character optional

^[a-zA-Z]?([a-zA-Z0-9]|\s(?!\s)){0,14}[^\s]$
johannes
This will also match strings not starting with `[a-zA-Z]` and not ending with `[a-zA-Z0-9]`.
Gumbo