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.
The _ (underscore) character in the regular expression means that the zone name must have an underscore immediately following the alphanumeric string matched by the preceding brackets. The . (period) matches any character (a wildcard).
is a positive lookahead, a type of zero-width assertion. What it's saying is that the captured match must be followed by whatever is within the parentheses but that part isn't captured. Your example means the match needs to be followed by zero or more characters and then a digit (but again that part isn't captured).
Throw in an * (asterisk), and it will match everything. Read more. \s (whitespace metacharacter) will match any whitespace character (space; tab; line break; ...), and \S (opposite of \s ) will match anything that is not a whitespace character.
You could use
^(?=^[^_]+_?[^_]+$)\w{3,20}$
See a demo on regex101.com (there are newline characters for demo purposes)
^ # 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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With