如何使用正则表达式验证用户名?

时间:2009-08-03 12:09:49

标签: regex

这似乎符合我定义的规则,但我今晚才开始学习正则表达式,所以我想知道它是否正确。

规则:

  • 用户名可以包含小写 和首都
  • 用户名可以包含字母数字 字符
  • 用户名可以包含下划线 和连字符和空格
  • 不能两个下划线,两个大肆宣传 或连续两个空格
  • 不能有下划线,夸张或 开始或结束时的空间

正则表达式:

/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/

10 个答案:

答案 0 :(得分:70)

问题中的规格不是很清楚,所以我只假设字符串只能包含ASCII字母和数字,连字符,下划线和空格作为内部分隔符。问题的关键在于确保第一个和最后一个字符不是分隔符,并且连续的行中永远不会有多个分隔符(无论如何,该部分看起来都很清楚)。这是最简单的方法:

/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/

匹配一个或多个字母数字字符后, if 有一个分隔符,必须后跟一个或多个字母数字字符;根据需要重复。

让我们从其他一些答案中看看正则表达式。

/^[[: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,这是一个非常罕见的功能,但你可以使用前瞻来达到同样的效果:

/^(?!.*[_\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]+$/

这是你自己的正则表达式,它要求字符串以两个字母数字字符开头和结尾,如果字符串中有两个分隔符,则它们之间必须有两个字母数字。因此abab-cdab-cd-ef会匹配,但aa-ba-b-c不会匹配。

此外,正如一些评论者指出的那样,正则表达式中的(_|-| )应为[-_ ]。那部分不是不正确的,但是如果你可以选择交替和字符类,你应该总是选择字符类:它们更高效,更可读。

同样,我并不担心“字母数字”是否应该包含非ASCII字符,或“空间”的确切含义,而是如何使用正则表达式强制实施非连续内部分隔符的策略。 / p>

答案 1 :(得分:21)

您可以将正则表达式简化为:

/^[a-zA-Z0-9]+([_ -]?[a-zA-Z0-9])*$/

使用Regexper显示:

Visualization of username validation regex.

如您所见,用户名始终必须以字母数字字符开头。特殊字符(_-)必须后跟字母数字字符。最后一个字符必须是字母数字字符。

答案 2 :(得分:4)

 ([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*

是0或更多重复的alphanum,dashspace,alphanum。

所以它会匹配

a_aa_aa_a

但不是

aaaaa

完整的正则表达式无法匹配

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,然后(在行规则中加入两个)a(alphanum或dashspace)*并再次和alphanum。

要防止连续两个虚线空间,您可能需要了解前瞻/后视。

哦,关于其他答案:请下载Espresso,它真的可以帮助你解决这些问题。

答案 3 :(得分:3)

我建议写一些单元测试来让Regex通过它的步伐。从现在开始,当您发现Regex出现问题并需要更新时,这也会有所帮助。

答案 4 :(得分:2)

  1. 字母数字不仅仅是[a-zA-Z0-9],还有重音符号,西里尔语,希腊语和其他字母,可以在用户名中使用。

  2. (_|-| )可以替换为[-_ ]字符类

答案 5 :(得分:1)

将POSIX字符类用于字母数字字符,使其适用于重音和其他外国字母字符:

/^[[:alnum:]]+([-_ ]?[[:alnum:]])*$/

更高效(防止捕获):

/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/

这些也可以防止组合使用多个空格/连字符/下划线的序列。 它不符合您的规范是否可取,而是您自己的正则表达式 似乎表明这就是你想要的。

答案 6 :(得分:0)

此处Expresso 3.0的另一个建议 - 非常容易使用和构建字符串。

答案 7 :(得分:0)

你的正则表达式不起作用。困难的部分是检查连续的空格/连字符。你可以使用这个,使用look-behind:

/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/

答案 8 :(得分:0)

从外观上看,该规则与“a_bc”,“ab_c”,“a_b”或“a_b_c”不匹配。

尝试:/^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/ 它匹配上述情况,但没有任何空格,破折号或下划线彼此相邻的组合。例如:不允许使用“_-”或“_”。

答案 9 :(得分:0)

我认为,对此模型添加有限范围会更好

[a-zA-Z0-9] +([_-]?[a-zA-Z0-9]){5,40} $

enter image description here