简体   繁体   中英

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.

regex101.com上的一些单元测试列表

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.

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.


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) 

还有一个变种:/ /^[a-z0-9](?:[a-z0-9]|_(?!.*_)){1,18}[a-z0-9]$/i :[ /^[a-z0-9](?:[a-z0-9]|_(?!.*_)){1,18}[a-z0-9]$/i

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM