这似乎符合我定义的规则,但我今晚才开始学习正则表达式,所以我想知道它是否正确。
规则:
- 用户名可以由小写字母组成 和首都
- 用户名可以由字母数字组成 字符
- 用户名可以包含下划线 以及连字符和空格
- 不能是两个下划线、两个连字符 或连续两个空格
- 不能有下划线、连字符或 开头或结尾有空格
正则表达式模式:
/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/
最佳答案
问题中的规范不是很清楚,所以我假设字符串只能包含 ASCII 字母和数字,并使用连字符、下划线和空格作为内部分隔符。问题的核心是确保第一个和最后一个字符不是分隔符,并且一行中永远不会有多个分隔符(无论如何,这部分看起来很清楚)。这是最简单的方法:
/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/
匹配一个或多个字母数字字符后,如果有分隔符,则后面必须跟一个或多个字母数字;根据需要重复。
让我们看看其他一些答案中的正则表达式。
/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/
这实际上是相同的(假设您的正则表达式风格支持 POSIX 字符类表示法),但为什么要使分隔符可选呢?您首先出现在正则表达式的该部分的唯一原因是是否存在分隔符或其他一些无效字符。
/^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/
另一方面,这只有效因为分隔符是可选的。在第一个分隔符之后,它一次只能匹配一个字母数字。为了匹配更多,它必须不断重复整个组:零分隔符后跟一个字母数字,一遍又一遍。如果第二个 [a-zA-Z0-9]
后跟一个加号,它可以通过更直接的路线找到匹配项。
/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/
这使用了无限制的lookbehind,这是一个非常罕见的功能,但是您可以使用lookahead来达到相同的效果:
/^(?!.*[_\s-]{2,})[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9]$/
这实际上对两个连续的分隔符执行单独的搜索,如果找到一个则匹配失败。然后主体只需要确保所有字符都是字母数字或分隔符,第一个和最后一个是字母数字。由于这两个字符是必需的,因此名称的长度必须至少为两个字符。
/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/
这是您自己的正则表达式,它要求字符串以两个字母数字字符开头和结尾,如果字符串中有两个分隔符,则它们之间必须恰好有两个字母数字。因此,ab
、ab-cd
和 ab-cd-ef
将匹配,但 a
、a-b
和 a-b-c
不会。
此外,正如一些评论者指出的那样,正则表达式中的 (_|-| )
应该是 [-_ ]
。这部分内容并没有不正确,但是如果您可以在交替和字符类之间进行选择,那么您应该始终选择字符类:它们更高效且更具可读性。
同样,我并不担心“字母数字”是否应该包含非 ASCII 字符,或者“空格”的确切含义,只是如何使用正则表达式强制执行非连续内部分隔符的策略。
关于regex - 如何使用正则表达式验证用户名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1221985/