如何使用正则expression式validation用户名?
这似乎符合我所定义的规则,但是我今晚才开始学习正则expression式,所以我想知道是否正确。
规则:
- 用户名可以由小写字母和大写字母组成
- 用户名可以由字母数字字符组成
- 用户名可以由下划线,连字符和空格组成
- 不能是两个下划线,连续两个或两个空格
- 在开始或结束时,不能有下划线,绞链或空格
正则expression式:
/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/
问题中的规格不是很清楚,所以我只假定string只能包含ASCII字母和数字,连字符,下划线和空格作为内部分隔符。 问题的症结在于确保第一个和最后一个字符不是分隔符,而且连续的分隔符也不会超过一个(反正这个部分看起来很清楚)。 这是最简单的方法:
/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/
匹配一个或多个字母数字字符后, 如果有分隔符,则必须紧跟一个或多个字母数字; 根据需要重复。
让我们看看来自其他答案的正则expression式。
/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/
这实际上是相同的(假设你的正则expression式风格支持POSIX字符类符号),但为什么使分隔符可选? 首先,你会在正则expression式的那一部分的唯一原因是如果有一个分隔符或其他一些无效的字符。
/^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/
另一方面,这只适用于分隔符是可选的。 在第一个分隔符后,一次只能匹配一个字母数字。 要匹配更多,它必须不断重复整个组:零分隔符后跟一个字母数字,一遍又一遍。 如果第二个[a-zA-Z0-9]
后面跟着一个加号,则可以通过更直接的路线find匹配。
/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/
这使用无限的lookbehind,这是一个非常罕见的function,但你可以使用一个向前看相同的效果:
/^(?!.*[_\s-]{2,})[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9]$/
这基本上是对两个连续的分隔符执行单独的search,如果find一个分隔符就会失败。 然后主体只需要确保所有的字符都是字母数字或分隔符,第一个和最后一个是字母数字。 由于这两个是必需的,所以这个名字必须至less有两个字符。
/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/
这是您自己的正则expression式,它需要string以两个字母数字字符开始和结束,如果string中有两个分隔符,则它们之间必须有两个字母数字。 所以ab
, ab-cd
和ab-cd-ef
会匹配,但a
, ab
和abc
不会。
另外,正如一些评论者指出的那样,正则expression式中的(_|-| )
应该是[-_ ]
。 这个部分没有错 ,但是如果你在一个交替和一个字符类之间有一个select,你应该总是和字符类一起使用:它们更高效,更具可读性。
再一次,我并不担心“字母数字”是否应该包含非ASCII字符,或“空间”的确切含义,只是如何使用正则expression式实施不连续的内部分隔符策略。
你的正则expression式可以简化为:
/^[a-zA-Z0-9]+([_ -]?[a-zA-Z0-9])*$/
使用Regexper进行可视化:
正如您所看到的,用户名始终必须以字母数字字符开头。 特殊字符( _
, ,
-
)必须跟随一个字母数字字符。 最后一个字符必须是字母数字字符。
([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*
是一个0或更多的alphanum,dashspace,alphanum的重复。
所以它会匹配
a_aa_aa_a
但不是
aaaaa
完整的正则expression式不能匹配
a_aaaaaaaaa_a for example.
让我们回头看看你想要什么:
* Usernames can consist of lowercase and capitals or alphanumerica characters * Usernames can consist of alphanumeric characters * Usernames can consist of underscore and hyphens and spaces * Cannot be two underscores, two hypens or two spaces in a row * Cannot have a underscore, hypen or space at the start or end
开始是简单的…只是匹配一个字母,然后(在排列规则中填入两个)一个(alphanum或dashspace)*和一个字母alphanum再次。
为了防止连续的两个虚线空间,您可能需要了解前瞻/后视。
噢,关于其他的答案:请下载咖啡,它真的帮助你不负责任的事情。
我build议编写一些unit testing,使正则expression式通过它的步伐。 这也将有助于几个月后,当你发现正则expression式的问题,并需要更新它。
-
字母数字不只是
[a-zA-Z0-9]
,它的重音,西里尔文,希腊文和其他字母,可以在用户名中使用。 -
(_|-| )
可以被[-_ ]
字符类replace
使用字母数字字符的POSIX字符类,使其适用于重音和其他外国字母字符:
/^[[:alnum:]]+([-_ ]?[[:alnum:]])*$/
更高效(防止捕获):
/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/
这些也防止多个空格/连字符/下划线组合的序列。 它不符合你的规范是否可取,但你自己的正则expression式似乎表明这是你想要的。
Expresso 3.0在这里的另一个build议 – 非常容易使用和build立string。
你的正则expression式不起作用。 困难的部分是检查连续的空格/连字符。 你可以使用这个,它使用后视:
/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/
从外观上看,这个规则不符合“a_bc”,“ab_c”,“a_b”或“a_b_c”之类的内容。
请尝试: /^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/
与上述情况相符,但不包含空格,破折号或强调彼此相邻。 例如:“_-”或“_”是不允许的。