正则表达式:解析GitHub用户名(JavaScript)

Sco*_*ott 6 javascript regex github

我试图从一段文本中解析GitHub用户名(以@开头),以便将它们链接到相关的配置文件.

GitHub用户名约束是:

  • 带单个连字符的字母数字(没有连续的连字符)
  • 不能以连字符开头或结尾(如果以连字符结尾,只需将所有内容匹配到那里)
  • 最大长度为39个字符.

例如,以下文字:

示例@valid hello @ valid-username:@ another-valid-username,@ -invalid @ in - valid @ ignore-last-dash- an@email.com @ another-valid?

剧本...

应该匹配:

  • @有效
  • @有效户名
  • @另一化有效的用户名
  • @在
  • @忽略 - 最后冲刺
  • @另一个-有效

应该忽略:

  • @-无效
  • an@email.com

我通过使用以下方式与JavaScript合理地接近:

/\B@((?!.*(-){2,}.*)[a-z0-9][a-z0-9-]{0,38}[a-z0-9])/ig
Run Code Online (Sandbox Code Playgroud)

但这不是用户名与单个字符匹配(例如@a).

以下是我的测试:https://regex101.com/r/rZ5eW1/2

目前的正则表达式是否有效?我如何匹配单个非连字符?

Fun*_*uit 5

/\B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))/gi
Run Code Online (Sandbox Code Playgroud)

注意:当此正则表达式遇到不能出现在用户名中的字符或字符集(即., --)时,它会从上到下匹配,@直到停止点为止。OP 说这很好,所以我正在接受它。因此,如果下划线是匹配区域(不是捕获区域):

/\B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))/gi
Run Code Online (Sandbox Code Playgroud)

这是通过使用大量嵌套组来实现的。Regex101 有一个很棒的细分,但这里是我的:

  1. \B:这是一个内置的意思是“不是单词边界”,这似乎可以解决问题,但如果类似的东西someones.@email.com是有效的电子邮件地址,则可能会出现问题。但是,在这一点上,当他们以@reference 开头的句子时,它与没有在标点符号[ 1 ]后放置空格的人的文本无法区分。

感谢 Honore Doktorr指出 JS 中不存在负向后视。

  1. @: 只是文字@符号。为数不多的几个地方之一,其中一个字符意味着它是什么。
  2. (...): 捕获组。它的放置方式意味着它不会捕获@符号,它只会匹配它,因此更容易获取用户名——无需获取子字符串。
  3. [a-z0-9]:匹配任何字母或数字的字符类。由于i标志,这也匹配大写字母。因为它是第一个字母,所以它必须存在。
  4. (?:...): 这是一个非捕获组。它将一个正则表达式块包装在一个组中而不捕获它。
  5. ...|... 我们有两种选择,它们是...
  6. -(?=[a-z0-9]): 一个连字符,后跟一个非连字符有效字符。
  7. [a-z0-9]: 一个有效的非连字符。
  8. {0,38}:匹配 0 到 38 次(含)之间的非捕获组。结合#4,这给了我们最多39 个字母。超出此范围的任何内容都将被忽略。
  9. (?<=[a-z0-9]):这是一个积极的回顾,JS 确实支持。它确保最后一个字符不是--- 或者更确切地说,是除连字符之外的有效字符。

这可以通过几种方式“优化”,但老实说,我可能会使用更简单的正则表达式并在事后对其进行一些验证,例如:

@abc.123
@abc--123
@abc-

至少,解释代码中的正则表达式。随意复制粘贴我的信用。