【问题标题】:Slightly complex regex for username稍微复杂的用户名正则表达式
【发布时间】:2015-09-20 15:40:00
【问题描述】:

我需要帮助来为用户名构建正则表达式。

用户名分为三个部分。第一个字符,中间组,最后一个字符。

以下是我必须遵守的规则:

  • 第一个字符必须是小写字母,例如(a-z)
  • 中间的字符组只能是 4 个或更多字符的字母和数字,例如(a-zA-Z0-9)
  • 中间组必须至少包含一个字母和一个数字
  • 最后一个字符必须是数字(0-9)

一些例子:

hTes38      (i.e. h Tes3 8)
j347k6      (i.e. j 347k 6)
atksde21D2  (i.e. a tksde21D 2)

这是我目前所拥有的,几乎就在那里:

^[a-z][a-zA-Z0-9]\w{1,}[0-9]$

但是中间组不正确,我不知道如何执行“必须包含一个字母和一个数字”的规则。

【问题讨论】:

  • 为什么你的尝试中有一个\w?为什么{1,} 应该是 4 个或更多?
  • @ooga 在一个阶段,我使用 4,然后尝试让它在一个阶段与单词一起工作,因此使用 (\w) 和 {1, },并尝试了许多其他变体。因此,我发布了不准确的正则表达式。道歉。

标签: regex


【解决方案1】:

使用两个前瞻(一个代表一个字母,一个代表一个数字)来断言中间部分至少有一个字母和一个数字:

^[a-z](?=.*[a-zA-Z])(?=.*\d.*.$)[a-zA-Z\d]{4,}\d$

请注意,数字 (?=.*\d.*.$) 的前瞻以 .*.$ 结尾,这确保整个输入的最后一位不会被计为中间部分的数字(最后一个点消耗最后一个数字,所以\d 无法匹配)。

请参阅live demo,了解您的示例和一些极端情况。

请参阅 this external article 了解环视的详细说明。

【讨论】:

  • 有个小错误:第一个char应该是(a-z)。
  • 试图让我的头脑围绕“向前看”,非常感谢!!!阅读此内容以完全理解它。
【解决方案2】:

如果您需要在单个正则表达式中执行此操作,Bohemian 有正确的答案。但是,根据您使用的语言/平台,运行由if 语句连接的多个正则表达式可能会更干净、更快捷。

if input.matches('^([a-z])([a-zA-Z0-9]{4,})([0-9])$'))
  if (matches[1].matches('\d') && matches[1].matches('[a-zA-Z]')
    return $true

return $false

如果您不能使用前瞻,也可以使用。

【讨论】:

  • 在 ASP.NET MVC (C#) 中的数据注释中使用它,并且 AFAIK 必须在单个语句中。但谢谢你。
【解决方案3】:

如果您想要清晰/简单,并且不限于单个正则表达式:

import re
s = "hTes38"
first, middle, last = s[0], s[1:-1], s[-1]
answer = bool(first.isalpha() and           # The first character must be a lower case letter
         last.isdigit() and                 # The last character must be a number
         len(middle) >= 4 and               # The middle group of characters must be 4 or more characters
         re.search("[a-zA-Z]", middle) and  # The middle group must contain at least one letter
         re.search(r"\d", middle) and       # AND one number
         re.match(r"[a-zA-Z\d]+$", middle)) # The middle group of characters must be letters and numbers only

【讨论】:

    【解决方案4】:

    如果你想要更直接和原始的东西,你总是可以尝试

    \d[a-zA-Z][a-zA-Z0-9][a-zA-Z0-9]|\d[a-zA-Z0-9][a-zA-Z][a-zA-Z0-9]|
    \d[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z]|[a-zA-Z]\d[a-zA-Z0-9][a-zA-Z0-9]|
    [a-zA-Z0-9]\d[a-zA-Z][a-zA-Z0-9]|[a-zA-Z0-9]\d[a-zA-Z0-9][a-zA-Z]|
    [a-zA-Z][a-zA-Z0-9]\d[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z]\d[a-zA-Z0-9]|
    [a-zA-Z0-9][a-zA-Z0-9]\d[a-zA-Z]|[a-zA-Z][a-zA-Z0-9][a-zA-Z0-9]\d|
    [a-zA-Z0-9][a-zA-Z][a-zA-Z0-9]\d|[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z]\d
    

    中间部分。这似乎工作得很好,但我没有用所有可能的组合测试它。

    这背后的一般逻辑是交替数字的位置(从位置 0 到 1 到 2 到 3),然后在其余位置中交替字符的位置(例如,如果数字在位置 1,则字符从 0 到 2 到 3) 交替,最后用数字或字符填充剩余的两个位置。

    注意:我绝对不是说这是最好的解决方案,但它仍然是一个解决方案。

    【讨论】:

    • 很高兴知道,会记下这种方法,谢谢。有另一种方法总是好的。
    • 不要使用\w来解决这个问题,因为它匹配_
    • 哎呀,我以为我设法避免了那个陷阱,但我想没有。它也匹配数字,这不是我想要的。总之,修好了。
    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 2011-02-15
    • 2011-07-12
    相关资源
    最近更新 更多