我想用以下规则验证用户名:
- 只能使用字符
a-z
、A-Z
、0-9
、_
、.
和-
- 字符
_
、.
和-
不能是第一个或最后一个字符 - 字符
_
、.
和-
不能相邻(符号之间必须至少有一个字母或数字字符) - 长度必须在3到15个字符之间,不包括任何
_
,.
和-
字符(必须有3-15个字母数字字符)
此时我使用以下正则表达式(点击查看):
/^(?=([A-Za-z0-9][-._]?){3,15}$)[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/
关于如何优化这个,特别是展望有什么想法吗?我试着向前看的(?=[^-._]{3,15})
,但它似乎没有工作。注意,我只能使用javascript兼容的regex。
有些人在遇到问题时,会想"我知道,我就用正则表达式吧!"现在他们有两个问题。杰米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-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]*$)
forward遵循对比:
如果可以,请使用互斥的连续标记,以创建对比。这减少了回溯和对广义边界的需求,我在这里包括了遍历。
如果你喜欢保留自己的正则表达式,我仍然建议注释它,并使用不区分大小写的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
首先,下面的模式应该是工作的
[a-zA-Z0-9](?:(?![_.-]{2})[a-zA-Z0-9_.-])+[a-zA-Z0-9]
From you conditions:
条件:字符_,.和-不能是
的第一个或最后一个字符
REGEX: [a-zA-Z0-9]...[a-zA-Z0-9]
和
CONDITION:只能使用字符a-z, a-z, 0-9, _, .和-
REGEX: [a-zA-Z0-9_.-]+
和
条件:字符_,.和-不能相邻
REGEX:(?![_.-]{2})
*在这里使用负向前看检查
但是…
最后一个条件
条件:长度必须在3到15个字符之间,不包括任何_,.,字符(必须有3-15个字母数字字符)
通过只计数字母数字字符来验证模式,我不知道。
我的结论
我不认为最后一个条件可以适合一个纯正则表达式,一旦你使用[...]+
来生成随机模式的匹配器,那么你如何使用向前看来验证这些模式,如果你不知道确切的模式。