我想使用以下规则验证用户名:
a-z
,A-Z
,0-9
,_
,.
和-
_
,.
和-
不能是第一个或最后一个字符_
,.
和-
不能彼此相邻(符号之间必须至少有一个字母数字字符)_
,.
和-
字符(必须有3-15个字母数字字符)我此时正在使用以下正则表达式(click to visualize):
/^(?=([A-Za-z0-9][-._]?){3,15}$)[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/
关于如何优化这一点的任何想法,尤其是前瞻性?我试过(?=[^-._]{3,15})
的前瞻,但它似乎没有用。请注意,我只能使用兼容Javascript的正则表达式。
答案 0 :(得分:2)
有些人在面对问题时会想“我知道,我会使用正则表达式!”现在他们有两个问题。 -Jamie Zawinsky
正则表达式可能有助于验证用户名,但您不应该尝试将其全部打包成一个正则表达式 - 这种方式就是疯狂。相反,打破它:
function isValidUsername(username) {
// may only use the characters a-z, A-Z, 0-9, _, ., and -
// the characters _, ., and - cannot be the first or last character
if(!/^[a-zA-Z0-9][a-zA-Z0-9_.-]+[a-zA-Z0-9]$/.test(username)) {
return false;
}
// the characters _, ., and - cannot be next to each other
// (there must be at least one alphanumeric character between symbols)
if(/[_.-]{2}/.test(username)) {
return false;
}
// must be between 3 and 15 characters in length,
// NOT INCLUDING any _, ., and - characters
// (there must be 3-15 alphanumeric characters)
var filteredUsername = username.replace(/[^a-zA-Z0-9]/g, '');
if(filteredUsername.length < 3 || filteredUsername.length > 15) {
return false;
}
return true;
}
我认为结果比将它们打包成一个正则表达式更容易维护,并且你可能也不会遇到任何性能问题。
答案 1 :(得分:0)
首先,下面的模式应该是正常的
[a-zA-Z0-9](?:(?![_\.\-]{2})[a-zA-Z0-9_\.\-])+[a-zA-Z0-9]
从你的条件:
条件:字符_,。和 - 不能是第一个或最后一个字符
REGEX: [a-zA-Z0-9]...[a-zA-Z0-9]
和
条件:只能使用字符a-z,A-Z,0-9,_,。和 -
REGEX: [a-zA-Z0-9_\.\-]+
和
条件:字符_,。和 - 不能彼此相邻
REGEX:(?![_\.\-]{2})
*这里只是使用负向前瞻来检查它
<强> BUT ... 强>
最后一个条件
条件:长度必须介于3到15个字符之间,不包括任何_ ,., 和字符(必须有3-15个字母数字字符)
通过仅计算字母数字字符来验证模式,我不知道。
我的结论是
我不认为最后一个条件可以通过纯正则表达式适合,一旦你使用[...]+
生成随机模式的匹配器,那么如何使用先行来验证这些模式,如果你不#39; t确切地知道前方的模式。
答案 2 :(得分:0)
您可以使用纯正的1-regex解决方案和优化的最后部分:
^(?=(?:[^a-zA-Z0-9]*[a-zA-Z0-9]){3,15}[^a-zA-Z0-9]*$)(?![._-])(?!.*[._-][._-])[\w.-]+[a-zA-Z0-9]$
请参阅regex demo(请注意,在多线模式下,\n
已添加到角色类以用于演示目的。)
如果应用了写正则表达式的伪详细样式,则可以使此正则表达式更易于维护和读取:
var re = RegExp(
"^" + // Beginning of a string
"(?=(?:[^a-z0-9]*[a-z0-9]){3,15}[^a-z0-9]*$)" + // Must contain 3-15 alphanums
"(?![._-])" + // Cannot start with ., _ or -
"(?!.*[._-][._-])" + // Cannot contain consecutive .-, -_, .., --, etc.
"[\\w.-]+[a-z0-9]" + // Consists of alphanums only and ends with a letter or digit
"$", // End of a string
"i"); // Make the pattern case-insensitive
var str = 'azzz-zzzzzzz_AZ0.9';
document.write(str + ": " + re.test(str)+"<br/>");
str = '.azzzzzzz-A_Z09';
document.write(str + ": " + re.test(str));
另请注意,(?=(?:[^a-z0-9]*[a-z0-9]){3,15}[^a-z0-9]*$)
前瞻后跟regex principle of contrast:
如果可以,请使用互斥的连续令牌以创建对比度。这减少了回溯以及广义上对边界的需求,其中包括了外观。
如果您希望保留自己的正则表达式,我仍然建议您对其进行评论并使用不区分大小写的i
修饰符来缩短它:
var re = RegExp(
"^" + // Beginning of a string
"(?=([a-z0-9][-._]?){3,15}$)" + // Must contain 3-15 alphanums (NOTE: only works if [-._] cannot follow one another)
"[a-z0-9]+" + // Cannot start with ., _ or -, starts only with letter or digit
"(?:[-._][a-z0-9]+)*" + // Cannot contain consecutive [._-], does not start/end with [-._]
"$", // End of a string
"i"); // Make pattern case insensitive