Regex:解析GitHub用户名(JavaScript)

Regex: parsing GitHub usernames (JavaScript)

本文关键字:JavaScript 用户 解析 GitHub Regex      更新时间:2023-09-26

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

GitHub用户名约束如下:

  • 单个连字符的字母数字(无连续连字符)
  • 不能以连字符开始或结束(如果以连字符结束,只需匹配直到那里的所有内容)
  • 最大长度39个字符。

例如:

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

脚本…

应该匹配:

  • @valid
  • @valid-username
  • @another-valid-username
  • @ in
  • @ignore-last-dash
  • @another-valid

应该忽略:

  • @-invalid
  • an.com

通过使用

,我可以合理地接近JavaScript:
/'B@((?!.*(-){2,}.*)[a-z0-9][a-z0-9-]{0,38}[a-z0-9])/ig

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

以下是我到目前为止的测试:https://regex101.com/r/rZ5eW1/2

当前正则表达式有效吗?如何匹配单个非连字符字符?

/'B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))/gi

注意:当这个正则表达式遇到一个字符或一组字符,不能在用户名(即., --),它匹配从@直到停止点。操作人员说没问题,所以我同意了。因此,如果下划线是匹配的区域(不是捕获的区域):

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

This works by using lots of nested groups. Regex101 has a fantastic breakdown, but here's mine anyway:

  1. 'B: This is a builtin means 'not a word boundary', which seems to do the trick, though it may be problematic if something like someones.@email.com is a valid email address. At that point, though, it's indistinguishable from the text of someone who doesn't put spaces after punctuation[1] when they start a sentence with an @reference.

Thanks to Honore Doktorr for pointing out that negative lookbehinds don't exist in JS.

  1. @: Just the literal @ symbol. One of the few places where a character means what it is.
  2. (...): The capturing group. The way it's placed means that it won't capture the @ symbol, it'll just match it, so it's easier to get the username -- no need to get a substring.
  3. [a-z0-9]: A character class to match any letter or number. Because of the i flag, this also matches capital letters. Because it's the first letter, it must be present.
  4. (?:...): This is a noncapturing group. It wraps a block of regex in a group without capturing it.
  5. ...|... We have two alternatives, which are...
  6. -(?=[a-z0-9]): A hyphen, followed immediately by a non-hyphen valid character.
  7. [a-z0-9]: A valid non-hyphen character.
  8. {0,38}: Match the noncapturing group between 0 and 38 times, inclusive. Combined with #4, this gives us 39 letters maximum. Anything beyond that will be ignored.
  9. (?<=[a-z0-9]): This is a positive lookbehind, which JS does support. It ensures the last character isn't a - -- or rather, is a valid character except hyphen.

This could be 'optimized' a few ways, but honestly, I'd probably use a much simpler regex and do some validation after-the-fact on it, e.g.:

// somehow get the prospective username into `user`
if (user.startsWith('-')) { /* reject */ }
if (user.endsWith('-')) { /* reject */ }
if (user.contains('--')) { /* reject */ }

至少要在代码中解释正则表达式。请随意复制粘贴,并注明出处。

这个表达式也将匹配您的一个单词的用户名。

/'B@(?!.*(-){2,}.*)[a-z0-9](?:[a-z0-9-]{0,37}[a-z0-9])?'b/ig

样本。解释:

  1. (?!.*(-){2,}.*):您的负前瞻断言模式的其余部分不能包含两个或多个相邻的破折号。
  2. [a-z0-9]: there 必须紧跟在@之后一个字母数字字符。
  3. (?:[a-z0-9-]{0,37}[a-z0-9])?: there 可以是0-37个字母数字字符或连字符,紧跟在#2模式之后的一个字母数字字符-或者可以没有,以覆盖单字符用户名。 (?:…)用于非捕获分组。
  4. 'b:整个模式必须以换行符结束(包括-)。

我使用这个简单的RegEx我创建抓取github用户名从谷歌表单,它的工作相当体面(有一个非常罕见的警告):

^@'w(-'w|'w'w|'w){0,19}$

地点:

  • ^:行起始
  • @-:符号at和破折号。
  • 'w: [A-Za-z0-9_],数字,字母(两种大小写)和下划线
  • $: line end
  • {0,19}:从0到19次重复前面的括号

总结:

  • 匹配的RegEx必须是一整行(从^$)
  • 它将以@开头,后跟字母(两种情况),数字或下划线(@A, @1@_)
  • 那么它将遵循重复模式(...){0,19}中的三个选项之一:

    • 一个破折号和一个'w (1st opt)
    • 'w (2nd opt)
    • 单个'w (3rd opt)

    这将重复并给出以下模式:

  • 0次:单个字母用户名

  • 一次:可以是两个字母的用户名,也可以是三个字母,或者三个字符中间有一个破折号@w-w
  • 更多次:它保证破折号永远不在开头或结尾,也不重复,在其他任何地方。
  • 19次:如果只使用第一个和第二个选项,它最多提供19*2=38个字符,加上开始的一个等于39个字符。如果在任何时候使用第三个选项,总大小将更小。

注意:

  • 它不识别带有@ww-w...w(第三个字母中的破折号和39个字符)的模式。
  • 虽然它可以识别模式@ww-w...w,如果大小小于39个字符。

问题在于,为了实现ww-w,模式被分解为单独的第一个w,然后是单个w作为重复表达式中的第三个选项(只剩下18个),然后是另一个重复作为w-(第一个选项,只剩下17个),然后,剩下这17个字符,我们只能得到17*2=34个字符。这意味着,最多将是38个(34+2+1+1)字符,而不是39个。

但这对我的目的来说真的很好,所以如果你需要简单,这里是一个RegEx,可以给你很好的答案。我希望它能帮助你在翻译成javascript时理解它