Jigar Jain
Jigar Jain

Reputation: 1447

jQuery regex for username

I want to implement a regex for usernames with the following conditions:

  1. The username will consist of only a-z, A-Z, 0-9 and - (hyphen);

  2. The username shall not consist of ONLY digits or ONLY hyphens but it can have only characters;

  3. The first & last characters shouldn't be hyphens (it can be digits but not entirely digits);

  4. Also, there shouldn't be 2 hyphens back to back;

  5. Minimum number of chars is 5 and max is 25;

So far I have tried this regex:

var filter = /(?=[a-zA-Z0-9-]{5,25}$)^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/;

It achieves conditions 1, 3, 4 and 5 correctly. But it doesn't fully satisfy condition 2. In my regex, it makes sure it doesn't consist entirely of hyphens. But it does allow only digits, which it shouldn't.

Can anyone let me know where I am going wrong or what needs to be done. Explanation of regex will be appreciated.

Upvotes: 1

Views: 2143

Answers (3)

dda
dda

Reputation: 6213

This seems to work in a quick test on my computer:

^(?![^-]*--+)(?![0-9]+$)[a-zA-Z0-9][-a-zA-Z0-9]{3,23}[a-zA-Z0-9]$

Explanation

^(?![^-]*--+)  No double (or more) hyphens
(?![0-9]+$)    Digits only forbidden
[a-zA-Z0-9]    Starts with a-z A-Z or 0-9
[-a-zA-Z0-9]{3,23}  Three to 23 more characters, including hyphens
[a-zA-Z0-9]$    Ends with a-z A-Z or 0-9

So that's 1 + (3 to 23) + 1 characters, ie 5 to 25.

Upvotes: 0

pete
pete

Reputation: 25091

For maintainability, things like this are usually better written as a series of tests rather than one big test.

var filter = function (username) {
    var allDigits = /^[0-9]+$/g,
        allHyphens = /^[-]+$/g, //doesn't need a character class, but I find it's more readable
        multiHyphens = /[-]+/g,
        startsWith = /^[A-Za-z0-9]{1}/,
        endsWith = /[A-Za-z0-9]{1}$/
        hasInvalidChars = /[^A-Za-z0-9-]/,
        meetsReqs = false;
    if (username.length >= 5 || username.length <= 25) { //ensure correct length
        meetsReqs = !allDigits.test(username);
        meetsReqs = meetsReqs && !allHyphens.test(username);
        meetsReqs = meetsReqs && !multiHyphens.test(username);
        meetsReqs = meetsReqs && !hasInvalidChars.test(username);
        meetsReqs = meetsReqs && startsWith.test(username);
        meetsReqs = meetsReqs && endsWith.test(username);
    }
    return meetsReqs;
};

Upvotes: 5

Jerry
Jerry

Reputation: 71578

You can add a negative lookahead at the beginning. I also placed the ^ anchor at the beginning of the expression.

^(?![0-9]+$)(?=[a-zA-Z0-9-]{5,25}$)[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$
 ^^^^^^^^^^^

This prevents against a match of ^[0-9]+$ which is in other words, a string with only numbers.

Upvotes: 3

Related Questions