6

我一直在与这些该死的事情作斗争。我记得曾经有一位讲师告诉我们,如果你有一个问题需要你使用正则表达式来解决它,你实际上现在有两个问题。

好吧,我当然同意这一点。正则表达式是我们不经常使用的东西,但是当我们这样做时,就像阅读一些外星语言(无论如何对我来说很好)......我想我会下定决心得到这本书并进一步阅读。

我面临的挑战是,我需要根据以下标准验证用户名:

  1. 可以包含字母,大写和小写
  2. 可以包含数字
  3. 可以包含句点 ( .) 和下划线 ( _)
  4. 句点和下划线不能连续,即__ ..不允许但._._有效。
  5. 总共最多 20 个字符

到目前为止,我有以下内容:^[a-zA-Z_.]{0,20}$但当然它允许重复下划线和句点。

现在,从一组有效字符和最大长度开始,我可能做错了。我一直在尝试(未成功)创建一些环视或后视或其他任何方法来搜索句点(.)和下划线(_)的无效重复,不确定将这个要求分解为正则表达式解决方案的方法或方法是什么。

任何人都可以协助推荐/替代方法或为我指明正确的方向吗?

4

3 回答 3

9

这个是你需要的:

^(?:[a-zA-Z0-9]|([._])(?!\1)){5,20}$

正则表达式可视化

在 Debuggex 上实时编辑

您可以在此处演示它匹配的内容。


“一个字母字符 ( [a-zA-Z0-9]) 或 ( |) 一个点或下划线 ( [._]),但后面不跟它本身 ( (?!\1)),而且是 5 到 20 次 ( {5,20})。”

  1. (?:X)只是一个非捕获组,即您不能在之后使用\1,$1?1语法来引用它。

  2. (?!X)被称为负前瞻,即字面意思是“后面没有 X”。

  3. \1指第一个捕获组。由于第一组(?:...){5,20}已设置为非捕获(请参阅#1),因此第一个捕获组是([._]).

  4. {X,Y}表示从 X 到 Y 次,您可以根据需要更改它。

于 2013-08-03T12:44:03.363 回答
6

您可以为此使用两个否定的前瞻性断言

^(?!.*__)(?!.*\.\.)[0-9a-zA-Z_.]{0,20}$ 

解释:

(?!  # Assert that it's impossible to match the following regex here:
 .*  # Any number of characters
 __  # followed by two underscores in a row
)    # End of lookahead

根据您的要求和您的正则表达式引擎,您可以替换[0-9A-Za-z_.][\w.].

@sp00n 提出了一个很好的观点:您可以将前瞻断言合并为一个:

^(?!.*(?:__|\.\.))[0-9a-zA-Z_.]{0,20}$

这可能更有效,但更难阅读。

于 2013-08-03T11:42:23.957 回答
6

不要试图把它塞进一个单一的正则表达式中。您的单个正则表达式适用于除#4 之外的所有标准。要执行 #4,只需执行匹配无效用户名的正则表达式,如果匹配则拒绝用户名。例如(在伪代码中):

if username.matches("^[a-zA-Z_.]{0,20}$") and !username.matches("__|\\.\\.") {
    /* accept username */
}
于 2013-08-03T11:42:50.740 回答