RegExp for matching usernames: min 3 chars, max 20 chars, optional underscore in between chars
I'm attempting to match roblox usernames (which follow these guidelines):
Minimum of 3 characters
Maximum of 20 characters
Maximum of 1 underscore
Underscore may not be at the beginning or end of the username
I am running on node.js version 10.12.0.
My current RegExp is:
/^([a-z0-9])(w)+([a-z0-9])$/i, but this does not account for the limit of 1 underscore.

javascript node.js regex
add a comment |
I'm attempting to match roblox usernames (which follow these guidelines):
Minimum of 3 characters
Maximum of 20 characters
Maximum of 1 underscore
Underscore may not be at the beginning or end of the username
I am running on node.js version 10.12.0.
My current RegExp is:
/^([a-z0-9])(w)+([a-z0-9])$/i, but this does not account for the limit of 1 underscore.

javascript node.js regex
1
Regular expressions are bad at counting. Did you consider solving this requirement in JavaScript instead?
– Micha Wiedenmann
Jan 27 at 19:17
@MichaWiedenmann: You don't really need to count for the condition to only have one underscore. It is completely achievable with negated character classes and anchors.
– Jan
Jan 27 at 19:31
He might have referred to the character limitation, where one may achieve a performance improvement by checking the string with.lengthin JavaScript.
– Siavas
Jan 27 at 20:06
While this problem can be solved by a single regex, the code is harder to understand. At least, when a positive lookahead is required to simulate matching two regexes simultaneouslystr.match(/^(?=regex1$)regex2$/), just use two regexesstr.match(/^regex1$/) && str.match(/^regex2$/).
– user202729
Jan 28 at 1:57
@Jan Yes, it is achievable, but that is not my point.
– Micha Wiedenmann
Jan 28 at 7:49
add a comment |
I'm attempting to match roblox usernames (which follow these guidelines):
Minimum of 3 characters
Maximum of 20 characters
Maximum of 1 underscore
Underscore may not be at the beginning or end of the username
I am running on node.js version 10.12.0.
My current RegExp is:
/^([a-z0-9])(w)+([a-z0-9])$/i, but this does not account for the limit of 1 underscore.

javascript node.js regex
I'm attempting to match roblox usernames (which follow these guidelines):
Minimum of 3 characters
Maximum of 20 characters
Maximum of 1 underscore
Underscore may not be at the beginning or end of the username
I am running on node.js version 10.12.0.
My current RegExp is:
/^([a-z0-9])(w)+([a-z0-9])$/i, but this does not account for the limit of 1 underscore.

javascript node.js regex
javascript node.js regex
edited Jan 27 at 19:50
Siavas
2,08611224
2,08611224
asked Jan 27 at 19:07
Jamie ClarkJamie Clark
515
515
1
Regular expressions are bad at counting. Did you consider solving this requirement in JavaScript instead?
– Micha Wiedenmann
Jan 27 at 19:17
@MichaWiedenmann: You don't really need to count for the condition to only have one underscore. It is completely achievable with negated character classes and anchors.
– Jan
Jan 27 at 19:31
He might have referred to the character limitation, where one may achieve a performance improvement by checking the string with.lengthin JavaScript.
– Siavas
Jan 27 at 20:06
While this problem can be solved by a single regex, the code is harder to understand. At least, when a positive lookahead is required to simulate matching two regexes simultaneouslystr.match(/^(?=regex1$)regex2$/), just use two regexesstr.match(/^regex1$/) && str.match(/^regex2$/).
– user202729
Jan 28 at 1:57
@Jan Yes, it is achievable, but that is not my point.
– Micha Wiedenmann
Jan 28 at 7:49
add a comment |
1
Regular expressions are bad at counting. Did you consider solving this requirement in JavaScript instead?
– Micha Wiedenmann
Jan 27 at 19:17
@MichaWiedenmann: You don't really need to count for the condition to only have one underscore. It is completely achievable with negated character classes and anchors.
– Jan
Jan 27 at 19:31
He might have referred to the character limitation, where one may achieve a performance improvement by checking the string with.lengthin JavaScript.
– Siavas
Jan 27 at 20:06
While this problem can be solved by a single regex, the code is harder to understand. At least, when a positive lookahead is required to simulate matching two regexes simultaneouslystr.match(/^(?=regex1$)regex2$/), just use two regexesstr.match(/^regex1$/) && str.match(/^regex2$/).
– user202729
Jan 28 at 1:57
@Jan Yes, it is achievable, but that is not my point.
– Micha Wiedenmann
Jan 28 at 7:49
1
1
Regular expressions are bad at counting. Did you consider solving this requirement in JavaScript instead?
– Micha Wiedenmann
Jan 27 at 19:17
Regular expressions are bad at counting. Did you consider solving this requirement in JavaScript instead?
– Micha Wiedenmann
Jan 27 at 19:17
@MichaWiedenmann: You don't really need to count for the condition to only have one underscore. It is completely achievable with negated character classes and anchors.
– Jan
Jan 27 at 19:31
@MichaWiedenmann: You don't really need to count for the condition to only have one underscore. It is completely achievable with negated character classes and anchors.
– Jan
Jan 27 at 19:31
He might have referred to the character limitation, where one may achieve a performance improvement by checking the string with
.length in JavaScript.– Siavas
Jan 27 at 20:06
He might have referred to the character limitation, where one may achieve a performance improvement by checking the string with
.length in JavaScript.– Siavas
Jan 27 at 20:06
While this problem can be solved by a single regex, the code is harder to understand. At least, when a positive lookahead is required to simulate matching two regexes simultaneously
str.match(/^(?=regex1$)regex2$/), just use two regexes str.match(/^regex1$/) && str.match(/^regex2$/).– user202729
Jan 28 at 1:57
While this problem can be solved by a single regex, the code is harder to understand. At least, when a positive lookahead is required to simulate matching two regexes simultaneously
str.match(/^(?=regex1$)regex2$/), just use two regexes str.match(/^regex1$/) && str.match(/^regex2$/).– user202729
Jan 28 at 1:57
@Jan Yes, it is achievable, but that is not my point.
– Micha Wiedenmann
Jan 28 at 7:49
@Jan Yes, it is achievable, but that is not my point.
– Micha Wiedenmann
Jan 28 at 7:49
add a comment |
4 Answers
4
active
oldest
votes
You could use
^(?=^[^_]+_?[^_]+$)w{3,20}$
See a demo on regex101.com (there are newline characters for demo purposes)
Broken down this is
^ # start of the string
(?=
^ # start of the string
[^_]+ # not an underscore, at least once
_? # an underscore
[^_]+ # not an underscore, at least once
$ # end of the string
)
w{3,20} # 3-20 alphanumerical characters
$ # end
The question has received quite some attention so I felt to add a non-regex version as well:
let usernames = ['gt_c', 'gt', 'g_t_c', 'gtc_', 'OnlyTwentyCharacters', 'poppy_harlow'];
let alphanumeric = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_']);
function isValidUsername(user) {
/* non-regex version */
// length
if (user.length < 3 || user.length > 20)
return false;
// not allowed to start/end with underscore
if (user.startsWith('_') || user.endsWith('_'))
return false;
// max one underscore
var underscores = 0;
for (var c of user) {
if (c == '_') underscores++;
if (!alphanumeric.has(c))
return false;
}
if (underscores > 1)
return false;
// if none of these returned false, it's probably ok
return true;
}
function isValidUsernameRegex(user) {
/* regex version */
if (user.match(/^(?=^[^_]+_?[^_]+$)w{3,20}$/))
return true;
return false;
}
usernames.forEach(function(username) {
console.log(username + " = " + isValidUsername(username));
});I personally think the regex version is shorter and cleaner but it's up to you to decide. Especially the alphanumeric part requires either some comparisons or a regex. With the latter in mind, you could use a regex version altogether.
2
Nice short solution, though I'm not sure OP's rules would allow other special characters than underscore, such as dash or non-ASCII.
– Siavas
Jan 27 at 19:32
2
This regex does not account for usernames with no underscore.
– Jamie Clark
Jan 27 at 19:46
@JamieClark: Now it does.
– Jan
Jan 27 at 20:37
add a comment |
Could be like this:
^(?=^w{3,20}$)[a-z0-9]+_?[a-z0-9]+$
| | | | | End with any alphanumeric
| | | |
| | | Optional underscore in middle
| | |
| | Start with any alphanumeric
| |
| Any accepted chars
| between 3 and 20 chars.
|
Start of string
The positive lookahead ensures the length will be of minimum 3 chars and maximum 20, and we check for an optional underscore in between one or more characters.
Try it here – I have added unit testing similar to yours as well.
add a comment |
If you consider using JS functions along with regex this is how i will do.
In matches i included all the matching strings by neglecting the _ condition and in final i am checking for the _ condition.
let str = `_vila
v_v
v__v
v_v
vvvvvv_
12345678912345678912
12345678912345678912123456`
let matches = str.match(/^[a-z0-9]w{1,18}[a-z0-9]$/gm)
let final = matches.map(e=> (e.split('_').length < 3 ? ({value:e,match:true}) : ({value:e,match:false})))
console.log(final)add a comment |
One more variant: /^[a-z0-9](?:[a-z0-9]|_(?!.*_)){1,18}[a-z0-9]$/i
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54391861%2fregexp-for-matching-usernames-min-3-chars-max-20-chars-optional-underscore-in%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could use
^(?=^[^_]+_?[^_]+$)w{3,20}$
See a demo on regex101.com (there are newline characters for demo purposes)
Broken down this is
^ # start of the string
(?=
^ # start of the string
[^_]+ # not an underscore, at least once
_? # an underscore
[^_]+ # not an underscore, at least once
$ # end of the string
)
w{3,20} # 3-20 alphanumerical characters
$ # end
The question has received quite some attention so I felt to add a non-regex version as well:
let usernames = ['gt_c', 'gt', 'g_t_c', 'gtc_', 'OnlyTwentyCharacters', 'poppy_harlow'];
let alphanumeric = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_']);
function isValidUsername(user) {
/* non-regex version */
// length
if (user.length < 3 || user.length > 20)
return false;
// not allowed to start/end with underscore
if (user.startsWith('_') || user.endsWith('_'))
return false;
// max one underscore
var underscores = 0;
for (var c of user) {
if (c == '_') underscores++;
if (!alphanumeric.has(c))
return false;
}
if (underscores > 1)
return false;
// if none of these returned false, it's probably ok
return true;
}
function isValidUsernameRegex(user) {
/* regex version */
if (user.match(/^(?=^[^_]+_?[^_]+$)w{3,20}$/))
return true;
return false;
}
usernames.forEach(function(username) {
console.log(username + " = " + isValidUsername(username));
});I personally think the regex version is shorter and cleaner but it's up to you to decide. Especially the alphanumeric part requires either some comparisons or a regex. With the latter in mind, you could use a regex version altogether.
2
Nice short solution, though I'm not sure OP's rules would allow other special characters than underscore, such as dash or non-ASCII.
– Siavas
Jan 27 at 19:32
2
This regex does not account for usernames with no underscore.
– Jamie Clark
Jan 27 at 19:46
@JamieClark: Now it does.
– Jan
Jan 27 at 20:37
add a comment |
You could use
^(?=^[^_]+_?[^_]+$)w{3,20}$
See a demo on regex101.com (there are newline characters for demo purposes)
Broken down this is
^ # start of the string
(?=
^ # start of the string
[^_]+ # not an underscore, at least once
_? # an underscore
[^_]+ # not an underscore, at least once
$ # end of the string
)
w{3,20} # 3-20 alphanumerical characters
$ # end
The question has received quite some attention so I felt to add a non-regex version as well:
let usernames = ['gt_c', 'gt', 'g_t_c', 'gtc_', 'OnlyTwentyCharacters', 'poppy_harlow'];
let alphanumeric = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_']);
function isValidUsername(user) {
/* non-regex version */
// length
if (user.length < 3 || user.length > 20)
return false;
// not allowed to start/end with underscore
if (user.startsWith('_') || user.endsWith('_'))
return false;
// max one underscore
var underscores = 0;
for (var c of user) {
if (c == '_') underscores++;
if (!alphanumeric.has(c))
return false;
}
if (underscores > 1)
return false;
// if none of these returned false, it's probably ok
return true;
}
function isValidUsernameRegex(user) {
/* regex version */
if (user.match(/^(?=^[^_]+_?[^_]+$)w{3,20}$/))
return true;
return false;
}
usernames.forEach(function(username) {
console.log(username + " = " + isValidUsername(username));
});I personally think the regex version is shorter and cleaner but it's up to you to decide. Especially the alphanumeric part requires either some comparisons or a regex. With the latter in mind, you could use a regex version altogether.
2
Nice short solution, though I'm not sure OP's rules would allow other special characters than underscore, such as dash or non-ASCII.
– Siavas
Jan 27 at 19:32
2
This regex does not account for usernames with no underscore.
– Jamie Clark
Jan 27 at 19:46
@JamieClark: Now it does.
– Jan
Jan 27 at 20:37
add a comment |
You could use
^(?=^[^_]+_?[^_]+$)w{3,20}$
See a demo on regex101.com (there are newline characters for demo purposes)
Broken down this is
^ # start of the string
(?=
^ # start of the string
[^_]+ # not an underscore, at least once
_? # an underscore
[^_]+ # not an underscore, at least once
$ # end of the string
)
w{3,20} # 3-20 alphanumerical characters
$ # end
The question has received quite some attention so I felt to add a non-regex version as well:
let usernames = ['gt_c', 'gt', 'g_t_c', 'gtc_', 'OnlyTwentyCharacters', 'poppy_harlow'];
let alphanumeric = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_']);
function isValidUsername(user) {
/* non-regex version */
// length
if (user.length < 3 || user.length > 20)
return false;
// not allowed to start/end with underscore
if (user.startsWith('_') || user.endsWith('_'))
return false;
// max one underscore
var underscores = 0;
for (var c of user) {
if (c == '_') underscores++;
if (!alphanumeric.has(c))
return false;
}
if (underscores > 1)
return false;
// if none of these returned false, it's probably ok
return true;
}
function isValidUsernameRegex(user) {
/* regex version */
if (user.match(/^(?=^[^_]+_?[^_]+$)w{3,20}$/))
return true;
return false;
}
usernames.forEach(function(username) {
console.log(username + " = " + isValidUsername(username));
});I personally think the regex version is shorter and cleaner but it's up to you to decide. Especially the alphanumeric part requires either some comparisons or a regex. With the latter in mind, you could use a regex version altogether.
You could use
^(?=^[^_]+_?[^_]+$)w{3,20}$
See a demo on regex101.com (there are newline characters for demo purposes)
Broken down this is
^ # start of the string
(?=
^ # start of the string
[^_]+ # not an underscore, at least once
_? # an underscore
[^_]+ # not an underscore, at least once
$ # end of the string
)
w{3,20} # 3-20 alphanumerical characters
$ # end
The question has received quite some attention so I felt to add a non-regex version as well:
let usernames = ['gt_c', 'gt', 'g_t_c', 'gtc_', 'OnlyTwentyCharacters', 'poppy_harlow'];
let alphanumeric = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_']);
function isValidUsername(user) {
/* non-regex version */
// length
if (user.length < 3 || user.length > 20)
return false;
// not allowed to start/end with underscore
if (user.startsWith('_') || user.endsWith('_'))
return false;
// max one underscore
var underscores = 0;
for (var c of user) {
if (c == '_') underscores++;
if (!alphanumeric.has(c))
return false;
}
if (underscores > 1)
return false;
// if none of these returned false, it's probably ok
return true;
}
function isValidUsernameRegex(user) {
/* regex version */
if (user.match(/^(?=^[^_]+_?[^_]+$)w{3,20}$/))
return true;
return false;
}
usernames.forEach(function(username) {
console.log(username + " = " + isValidUsername(username));
});I personally think the regex version is shorter and cleaner but it's up to you to decide. Especially the alphanumeric part requires either some comparisons or a regex. With the latter in mind, you could use a regex version altogether.
let usernames = ['gt_c', 'gt', 'g_t_c', 'gtc_', 'OnlyTwentyCharacters', 'poppy_harlow'];
let alphanumeric = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_']);
function isValidUsername(user) {
/* non-regex version */
// length
if (user.length < 3 || user.length > 20)
return false;
// not allowed to start/end with underscore
if (user.startsWith('_') || user.endsWith('_'))
return false;
// max one underscore
var underscores = 0;
for (var c of user) {
if (c == '_') underscores++;
if (!alphanumeric.has(c))
return false;
}
if (underscores > 1)
return false;
// if none of these returned false, it's probably ok
return true;
}
function isValidUsernameRegex(user) {
/* regex version */
if (user.match(/^(?=^[^_]+_?[^_]+$)w{3,20}$/))
return true;
return false;
}
usernames.forEach(function(username) {
console.log(username + " = " + isValidUsername(username));
});let usernames = ['gt_c', 'gt', 'g_t_c', 'gtc_', 'OnlyTwentyCharacters', 'poppy_harlow'];
let alphanumeric = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_']);
function isValidUsername(user) {
/* non-regex version */
// length
if (user.length < 3 || user.length > 20)
return false;
// not allowed to start/end with underscore
if (user.startsWith('_') || user.endsWith('_'))
return false;
// max one underscore
var underscores = 0;
for (var c of user) {
if (c == '_') underscores++;
if (!alphanumeric.has(c))
return false;
}
if (underscores > 1)
return false;
// if none of these returned false, it's probably ok
return true;
}
function isValidUsernameRegex(user) {
/* regex version */
if (user.match(/^(?=^[^_]+_?[^_]+$)w{3,20}$/))
return true;
return false;
}
usernames.forEach(function(username) {
console.log(username + " = " + isValidUsername(username));
});edited Jan 28 at 19:04
answered Jan 27 at 19:27
JanJan
26k52750
26k52750
2
Nice short solution, though I'm not sure OP's rules would allow other special characters than underscore, such as dash or non-ASCII.
– Siavas
Jan 27 at 19:32
2
This regex does not account for usernames with no underscore.
– Jamie Clark
Jan 27 at 19:46
@JamieClark: Now it does.
– Jan
Jan 27 at 20:37
add a comment |
2
Nice short solution, though I'm not sure OP's rules would allow other special characters than underscore, such as dash or non-ASCII.
– Siavas
Jan 27 at 19:32
2
This regex does not account for usernames with no underscore.
– Jamie Clark
Jan 27 at 19:46
@JamieClark: Now it does.
– Jan
Jan 27 at 20:37
2
2
Nice short solution, though I'm not sure OP's rules would allow other special characters than underscore, such as dash or non-ASCII.
– Siavas
Jan 27 at 19:32
Nice short solution, though I'm not sure OP's rules would allow other special characters than underscore, such as dash or non-ASCII.
– Siavas
Jan 27 at 19:32
2
2
This regex does not account for usernames with no underscore.
– Jamie Clark
Jan 27 at 19:46
This regex does not account for usernames with no underscore.
– Jamie Clark
Jan 27 at 19:46
@JamieClark: Now it does.
– Jan
Jan 27 at 20:37
@JamieClark: Now it does.
– Jan
Jan 27 at 20:37
add a comment |
Could be like this:
^(?=^w{3,20}$)[a-z0-9]+_?[a-z0-9]+$
| | | | | End with any alphanumeric
| | | |
| | | Optional underscore in middle
| | |
| | Start with any alphanumeric
| |
| Any accepted chars
| between 3 and 20 chars.
|
Start of string
The positive lookahead ensures the length will be of minimum 3 chars and maximum 20, and we check for an optional underscore in between one or more characters.
Try it here – I have added unit testing similar to yours as well.
add a comment |
Could be like this:
^(?=^w{3,20}$)[a-z0-9]+_?[a-z0-9]+$
| | | | | End with any alphanumeric
| | | |
| | | Optional underscore in middle
| | |
| | Start with any alphanumeric
| |
| Any accepted chars
| between 3 and 20 chars.
|
Start of string
The positive lookahead ensures the length will be of minimum 3 chars and maximum 20, and we check for an optional underscore in between one or more characters.
Try it here – I have added unit testing similar to yours as well.
add a comment |
Could be like this:
^(?=^w{3,20}$)[a-z0-9]+_?[a-z0-9]+$
| | | | | End with any alphanumeric
| | | |
| | | Optional underscore in middle
| | |
| | Start with any alphanumeric
| |
| Any accepted chars
| between 3 and 20 chars.
|
Start of string
The positive lookahead ensures the length will be of minimum 3 chars and maximum 20, and we check for an optional underscore in between one or more characters.
Try it here – I have added unit testing similar to yours as well.
Could be like this:
^(?=^w{3,20}$)[a-z0-9]+_?[a-z0-9]+$
| | | | | End with any alphanumeric
| | | |
| | | Optional underscore in middle
| | |
| | Start with any alphanumeric
| |
| Any accepted chars
| between 3 and 20 chars.
|
Start of string
The positive lookahead ensures the length will be of minimum 3 chars and maximum 20, and we check for an optional underscore in between one or more characters.
Try it here – I have added unit testing similar to yours as well.
edited Jan 27 at 20:07
answered Jan 27 at 19:29
SiavasSiavas
2,08611224
2,08611224
add a comment |
add a comment |
If you consider using JS functions along with regex this is how i will do.
In matches i included all the matching strings by neglecting the _ condition and in final i am checking for the _ condition.
let str = `_vila
v_v
v__v
v_v
vvvvvv_
12345678912345678912
12345678912345678912123456`
let matches = str.match(/^[a-z0-9]w{1,18}[a-z0-9]$/gm)
let final = matches.map(e=> (e.split('_').length < 3 ? ({value:e,match:true}) : ({value:e,match:false})))
console.log(final)add a comment |
If you consider using JS functions along with regex this is how i will do.
In matches i included all the matching strings by neglecting the _ condition and in final i am checking for the _ condition.
let str = `_vila
v_v
v__v
v_v
vvvvvv_
12345678912345678912
12345678912345678912123456`
let matches = str.match(/^[a-z0-9]w{1,18}[a-z0-9]$/gm)
let final = matches.map(e=> (e.split('_').length < 3 ? ({value:e,match:true}) : ({value:e,match:false})))
console.log(final)add a comment |
If you consider using JS functions along with regex this is how i will do.
In matches i included all the matching strings by neglecting the _ condition and in final i am checking for the _ condition.
let str = `_vila
v_v
v__v
v_v
vvvvvv_
12345678912345678912
12345678912345678912123456`
let matches = str.match(/^[a-z0-9]w{1,18}[a-z0-9]$/gm)
let final = matches.map(e=> (e.split('_').length < 3 ? ({value:e,match:true}) : ({value:e,match:false})))
console.log(final)If you consider using JS functions along with regex this is how i will do.
In matches i included all the matching strings by neglecting the _ condition and in final i am checking for the _ condition.
let str = `_vila
v_v
v__v
v_v
vvvvvv_
12345678912345678912
12345678912345678912123456`
let matches = str.match(/^[a-z0-9]w{1,18}[a-z0-9]$/gm)
let final = matches.map(e=> (e.split('_').length < 3 ? ({value:e,match:true}) : ({value:e,match:false})))
console.log(final)let str = `_vila
v_v
v__v
v_v
vvvvvv_
12345678912345678912
12345678912345678912123456`
let matches = str.match(/^[a-z0-9]w{1,18}[a-z0-9]$/gm)
let final = matches.map(e=> (e.split('_').length < 3 ? ({value:e,match:true}) : ({value:e,match:false})))
console.log(final)let str = `_vila
v_v
v__v
v_v
vvvvvv_
12345678912345678912
12345678912345678912123456`
let matches = str.match(/^[a-z0-9]w{1,18}[a-z0-9]$/gm)
let final = matches.map(e=> (e.split('_').length < 3 ? ({value:e,match:true}) : ({value:e,match:false})))
console.log(final)answered Jan 27 at 19:25
Code ManiacCode Maniac
10.7k2733
10.7k2733
add a comment |
add a comment |
One more variant: /^[a-z0-9](?:[a-z0-9]|_(?!.*_)){1,18}[a-z0-9]$/i
add a comment |
One more variant: /^[a-z0-9](?:[a-z0-9]|_(?!.*_)){1,18}[a-z0-9]$/i
add a comment |
One more variant: /^[a-z0-9](?:[a-z0-9]|_(?!.*_)){1,18}[a-z0-9]$/i
One more variant: /^[a-z0-9](?:[a-z0-9]|_(?!.*_)){1,18}[a-z0-9]$/i
answered Jan 27 at 19:39
vsemozhetbytvsemozhetbyt
2,213711
2,213711
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54391861%2fregexp-for-matching-usernames-min-3-chars-max-20-chars-optional-underscore-in%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown

1
Regular expressions are bad at counting. Did you consider solving this requirement in JavaScript instead?
– Micha Wiedenmann
Jan 27 at 19:17
@MichaWiedenmann: You don't really need to count for the condition to only have one underscore. It is completely achievable with negated character classes and anchors.
– Jan
Jan 27 at 19:31
He might have referred to the character limitation, where one may achieve a performance improvement by checking the string with
.lengthin JavaScript.– Siavas
Jan 27 at 20:06
While this problem can be solved by a single regex, the code is harder to understand. At least, when a positive lookahead is required to simulate matching two regexes simultaneously
str.match(/^(?=regex1$)regex2$/), just use two regexesstr.match(/^regex1$/) && str.match(/^regex2$/).– user202729
Jan 28 at 1:57
@Jan Yes, it is achievable, but that is not my point.
– Micha Wiedenmann
Jan 28 at 7:49