如何在Javascript中将这两个正则表达式组合?

3

我编写了一个Javascript程序,可以根据主机名或URL找到根域名

function getRootDomain(s){
  var sResult = ''
  try {
    sResult = s.match(/^(?:.*\:\/?\/)?(?<domain>[\w\-\.]*)/).groups.domain
      .match(/(?<root>[\w\-]*(\.\w{3,}|\.\w{2}|\.\w{2}\.\w{2}))$/).groups.root;
  } catch(ignore) {}
  return sResult;
}

什么技巧可以将两个正则表达式规则合并为一个规则?
我使用了这篇教程来提高多年来的正则表达式经验,尽管我从未真正理解过回顾和前瞻(这可能在这里有用?),然后使用RegEx101.com上的优秀工具进行试错。我尝试的是将<root>之后的内容粘贴到<domain>之后的内容中,并对此进行变化,但所有尝试都失败了。
可用于类似RegEx101的工具的测试集可以是:
https://test.com:8080/?id=4&re=3
https://test-test.com:8080/?id=4&re=3
https://data.test.com:8080/?id=4&re=3
https://data.test.com/?id=4&re=3
https://data.test.com/
https://data.test.com#testing
https://data.test.com/#testing
https://data.test.com:8080/#testing
https://data.test.com:8080#testing
https://data.tester.com/
https://data-test.test.com/
https://test.com
https://test.com#testing
https://test.com/
https://test.am/?id=4
https://test.com?id=3&re=3
https://test.com/?id=3&re=3
https://megatest.com/?id=3&re=3

test.com
data.test.co.uk
test.co
data.test.com
data.tester-test.com
data-test.tester-test.com
tester-test.com
about:blank

哦,我刚才才注意到答案是你发布的。我原以为是其他人在问如何改进你的答案。 - Barmar
1
当我查看其他答案时,我注意到了你的声誉。就像我说的那样,我没有注意到这是你发布的。 - Barmar
1个回答

1
第二个正则表达式使用$断言仅匹配.domain的结尾。
然而,第一个RegExp在域名后停止匹配(遇到/?#:或字符串结尾(如果没有路径、查询字符串或哈希部分)。因此,您不能只是重用$断言,否则会在某些情况下失败。
要合并两个部分,可以将domain捕获替换为以下内容: .*?(?<root>[\w\-]*(\.\w{2,}|\.\w{2}\.\w{2}|\.\w{3,}))(?:[\/?#:]|$) 结尾处的(?:[\/?#]|$)是一个非捕获组,它匹配目标字符或字符串的结尾。 .*?节约地匹配任何内容。也就是说,它首先尝试匹配root捕获,然后跟随(?:[\/?#]|$)。每次失败时,它都会吃掉一个字符并再次尝试,让您搜索root
此外:
  • 您可以将\.\w{3,}|\.\w{2}合并为\.\w{2,}

  • 您可以在TLD周围使用非捕获组((?:...) vs (...))。

  • 最好使用.*?来获取协议,否则可能会匹配太多内容(使用贪婪的.*,传递https://example.com/#://bar.com将返回bar.com)。

  • 您不需要转义:。在Unicode模式下,该转义实际上是语法错误。

结果为:
const x = /^(?:.*?:\/\/)?.*?(?<root>[\w\-]*(?:\.\w{2,}|\.\w{2}\.\w{2}))(?:[\/?#:]|$)/

我实际上写了一个正则表达式生成器,可以帮助你在学习正则表达式的旅程中更进一步...这里是你的正则表达式在compose-regexp中的转换结果


1
这个可以用。你需要进行一些小修改来处理域名上的潜在端口号,例如 https://data.test.com:8080/。这是我所做的更改:/^(?:.*\:\/?\/)?.*?(?<root>[\w\-]*(\.\w{2,}|\.\w{2}\.\w{2}))(?:[\:\/?#]|$)/ 我在 regex101.com 上测试过了。 - Volomike
1
太棒了,@Volomike,谢谢!我已经相应地更新了答案。(还有感谢你的点赞,我终于可以在这里发表评论了,真是太好了 :-) - Pygy
1
@volomike,我对响应进行了微调,并进行了进一步的改进。希望你会发现它们有用。 - Pygy
它出现在你的正则表达式中(应用于第一个“/”,我将其移动到第二个位置,以便将“':/”放在同一个字符串中),我认为你有充分的理由将其放在那里... - Pygy
1
我使用我的编辑权限,编辑了你的答案,去掉了那个不必要的额外问号。 - Volomike
显示剩余2条评论

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