验证用户名的正则表达式

117
我正在尝试创建一个正则表达式来验证用户名是否符合以下标准:
  1. 只包含字母数字字符、下划线和点。
  2. 下划线和点不能在用户名的开头或结尾(例如 _username / username_ / .username / username.)。
  3. 下划线和点不能相邻(例如 user_.name)。
  4. 下划线或点不能连续使用(例如 user__name / user..name)。
  5. 字符数必须在8到20之间。
到目前为止,这是我做的;它似乎符合所有标准规则,但不包括第五条规则。我不知道如何将第五条规则添加到这个表达式中。
^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$

编程相关的内容翻译成中文。仅返回翻译后的文本:每次只允许使用一个下划线或点号。 - mohsen dorparasti
但 a_b_c_d_e 是有效的,对吗? - Patrick McDonald
是的,没错。我正在测试你的正则表达式,听起来工作正常 :) - mohsen dorparasti
如果用非点号分隔,是否可以有多个点?例如:"A.B.C"(下划线同理)? - ridgerunner
语法高亮(如果可以这样称呼)在这个例子中没有问题,并且实际上提供了一些价值。在这种情况下,在Stack Overflow上,默认情况下可能是从ASP.NET标签中获取的(“代码语言”(不管这意味着什么 - 可能是指没有提示的情况下,正则表达式将被突出显示为C#))。 - undefined
12个回答

439
^(?=.{8,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$
 └─────┬────┘└───┬──┘└─────┬─────┘└─────┬─────┘ └───┬───┘
       │         │         │            │           no _ or . at the end
       │         │         │            │
       │         │         │            allowed characters
       │         │         │
       │         │         no __ or _. or ._ or .. inside
       │         │
       │         no _ or . at the beginning
       │
       username is 8-20 characters long

如果您的浏览器由于缺少负向回顾支持而引发错误,请使用以下替代模式:

^(?=[a-zA-Z0-9._]{8,20}$)(?!.*[_.]{2})[^_.].*[^_.]$

20
@ridgerunner - 我相信这样写容易阅读和转换为代码。 - Ωmega
3
@vigneshkumar - 相同的含义,但 [a-zA-Z0-9._] 更易于阅读和理解。 - Ωmega
2
(?<![_.])$ 中的 < 对我来说会导致解析错误,显示为“无效的正则表达式”。 - Jackson Lenhart
3
你使用哪种正则表达式引擎和编程语言?请注意,这个问题被标记为 asp.net 标签,虽然回答适用于大多数其他语言和引擎,但并非所有支持负向先行断言和后顾断言的零长度断言。 - Ωmega
3
请注意,这个正则表达式会导致Angular应用在IOS设备和Firefox浏览器上崩溃。 - Karan Jagtiani
显示剩余8条评论

16
我猜你需要在这里使用Lookahead表达式。请查阅http://www.regular-expressions.info/lookaround.html 尝试: ^[a-zA-Z0-9](_(?!(\.|_))|\.(?!(_|\.))|[a-zA-Z0-9]){6,18}[a-zA-Z0-9]$ [a-zA-Z0-9]表示一个字母或数字,然后(

_(?!\.)一个下划线而不是跟着一个句点 OR

\.(?!_)一个句点而不是跟着一个下划线 OR

[a-zA-Z0-9]一个字母或数字 ) FOR

{6,18}最少6个,最多18个字符,然后

[a-zA-Z0-9]一个字母或数字
(第一个字符是字母或数字,总长度为8至20个字符)。

尝试:^[a-zA-Z0-9](_(?!(\.|_))|\.(?!(_|\.))|[a-zA-Z0-9]){6,18}[a-zA-Z0-9]$ - Adam Wolski
3
可以的。但是 (_|\.) 表达式可以简化为 [_.] - ridgerunner
很好,如果有人需要JS的这种RegEx,这就是方法。它在所有浏览器中都可以工作,不像得票最多的答案只能在Chrome中使用。 - ElRey777

15
尽管我非常喜欢正则表达式,但我认为可读性是有限度的。
所以我建议
new Regex("^[a-z._]+$", RegexOptions.IgnoreCase).IsMatch(username) &&
!username.StartsWith(".") &&
!username.StartsWith("_") &&
!username.EndsWith(".") &&
!username.EndsWith("_") &&
!username.Contains("..") &&
!username.Contains("__") &&
!username.Contains("._") &&
!username.Contains("_.");

虽然这段话比较长,但不需要维护者打开 expresso 来理解。

当然,你可以对一个长的正则表达式进行注释,但是读者必须依赖信任。


1
那是用什么语言写的?C#吗? - undefined
@PeterMortensen 是的,具体来说是.NET。RegexOptions 枚举来自 System.Text.RegularExpressions 命名空间 - undefined

9
菲利普的答案稍作修改即可解决最新要求。
^[a-zA-Z0-9]([._](?![._])|[a-zA-Z0-9]){6,18}[a-zA-Z0-9]$

这在字符限制规则中存在问题,给定规则为{6,18}时,最少接受8个字符,然而应该接受6个字符。如果我将其改为{4,18},则它将接受6个字符,而我已经定义为4个。 - Ibrahim Azhar Armar

4
private static final Scanner scan = new Scanner(System.in);

public static void main(String[] args) {
    int n = Integer.parseInt(scan.nextLine());
    while (n-- != 0) {
        String userName = scan.nextLine();
        String regularExpression = "^[[A-Z]|[a-z]][[A-Z]|[a-z]|\\d|[_]]{7,29}$";
        if (userName.matches(regularExpression)) {
            System.out.println("Valid");
        } else {
            System.out.println("Invalid");
        }
    }
}

1
需要解释一下。 - undefined

3
^(?=.{4,20}$)(?:[a-zA-Z\d]+(?:(?:\.|-|_)[a-zA-Z\d])*)+$

您可以在这里测试正则表达式。

2
这允许在开头和结尾使用下划线,这是不希望的。 - Toto
2
它还可以匹配仅包含下划线的无限长字符串。 - Toto
1
@Toto,我已经修复了。 - FrEqDe
1
运行良好,但允许“-”字符,我在这里进行了一些调整:^(?=.{4,20}$)(?:[a-zA-Z\d]+(?:[._][a-zA-Z\d])*)+$,这对我很有帮助,感谢@FrEqDe提供的代码。 - Eazy

2

另一个问题中偶然发现了这个问题。看起来没有必要使用那么多的lookaround。 可以使用稍微缩短的模式,使用\w,它是“单词字符”的简称,通常设置为[A-Za-z0-9_]。为了摆脱下划线,可以使用 [^\W_]来匹配[A-Za-z0-9]

^[^\W_](?!.*?[._]{2})[\w.]{6,18}[^\W_]$
  • ^[^\W_] 一个字母或数字在start
  • (?!.*?[._]{2}) 负向前瞻以禁止__ ._ _. ..
    (为了减少对更长输入的步骤,.*?中使用了惰性量词)
  • [\w.]{6,18} 6到18个字符,可以是字母、数字、_.
  • [^\W_]$ 以另一个字母或数字结尾

请在regex101上查看此演示(右侧有进一步的解释)

注意:根据环境/设置,\w 还可以包含 Unicode 字母和数字。


1

^[a-z0-9_-]{3,15}$

^ # 行的开头

[a-z0-9_-] # 匹配列表中的字符和符号,包括 a-z、0-9、下划线、连字符

{3,15} # 长度至少为 3 个字符,最大长度为 15 个字符

$ # 行的结尾


0
const regex = /^moe_(app|lab)[A-Za-z0-9]{3}$/;
const str = `moe_app_baa`;
let m;

if ((m = regex.exec(str)) !== null) {
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community
OP正在使用ASP.NET。虽然这并不排除他们使用JavaScript的可能性,但如果回答与OP指定的语言不同,最好明确说明,并提供理由。 - undefined

0

这个应该能解决问题:

if (Regex.IsMatch(text, @"
    # Validate username with 5 constraints.
    ^                          # Anchor to start of string.
    # 1- only contains alphanumeric characters , underscore and dot.
    # 2- underscore and dot can't be at the end or start of username,
    # 3- underscore and dot can't come next to each other.
    # 4- each time just one occurrence of underscore or dot is valid.
    (?=[A-Za-z0-9]+(?:[_.][A-Za-z0-9]+)*$)
    # 5- number of characters must be between 8 to 20.
    [A-Za-z0-9_.]{8,20}        # Apply constraint 5.
    $                          # Anchor to end of string.
    ", RegexOptions.IgnorePatternWhitespace))
{
    // Successful match
} else {
    // Match attempt failed
} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接