正则表达式 - 提取子域名和域名

40

我正在尝试编写一个正则表达式(javascript/node.js),它可以从任何给定的URL中提取子域名和域名部分。以下是我得到的正则表达式:

[^(?:http:\/\/|www\.|https:\/\/)]([^\/]+)

目前,我只考虑http、https协议,并从URL的子域名+域名部分中排除"www."。我检查了表达式,它几乎可以工作。但是,这里有一个问题:

成功

'http://mplay.google.co.in/sadfask/asdkfals?dk=10'.match(/[^(?:http:\/\/|www\.|https:\/\/)]([^\/]+)/i)

'http://lplay.google.co.in/sadfask/asdkfals?dk=10'.match(/[^(?:http:\/\/|www\.|https:\/\/)]([^\/]+)/i)

失败

'http://play.google.co.in/sadfask/asdkfals?dk=10'.match(/[^(?:http:\/\/|www\.|https:\/\/)]([^\/]+)/i)

'http://tplay.google.co.in/sadfask/asdkfals?dk=10'.match(/[^(?:http:\/\/|www\.|https:\/\/)]([^\/]+)/i)

我只是使用结果数组中的第一个元素。我无法理解为什么 "play." 和 "tplay." 不起作用。请有人在这方面帮助我吗?
"/p" 和 "/t" 在正则表达式求值器中有任何含义吗?
是否有其他方法可以使用正则表达式从任何给定的 URL 中提取子域和域?
编辑 -
例子: https://play.google.com/store/apps/details?id=com.skgames.trafficracer => play.google.com https://mail.google.com/mail/u/0/#inbox => mail.google.com
7个回答

100
你的正则表达式似乎不正确。试试这个正则表达式:
/^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:\/\n?]+)/img

域名将在捕获组#1中可用。

正则表达式演示

正则表达式详细信息:

  • ^:匹配开头
  • (?:https?:\/\/)?:匹配可选文本https://
  • (?:[^@\n]+@)?:匹配可选文本后跟1个或多个任意文本和@
  • (?:www\.)?:匹配可选文本www.
  • ([^:\/\n?]+):匹配1个或多个不是(换行符和/?:)的任意字符,并将此值捕获在捕获组#1中

如果我只想要域名而不包括http(s)或www的内容怎么办? - kuklei
1
这就是你在上面的正则表达式中捕获组#1得到的结果。检查演示。 - anubhava

25

你是第一百万尝试在JavaScript中解析URL的人。我有点惊讶你没有看到几年前的SO上的任何现有问题。最后你想做的是写另一个已经失效的正则表达式,对于那些回答你问题的人,我表示敬意。

有许多文档完整且可靠的库和方法可以处理这个问题。去谷歌一下吧。最简单的方法是在内存中创建一个元素,给它分配一个href,然后访问它的hostname和其他属性。参见 http://tutorialzine.com/2013/07/quick-tip-parse-urls/。如果这不适合你,那么使用像 uri.js 这样的库。

如果你真的不想使用库,并坚持要重新发明轮子,那么请至少像下面这样做:

function get_domain_from_url(url) {
    var a = document.createElement('a').
    a.setAttribute('href', url);
    return a.hostname;
}

基本上,您将 URL 的子域/域部分的提取委托给浏览器的 URL 解析逻辑,这比您编写的任何内容都要好得多。

另请参见使用 jQuery/JavaScript 解析 URL?使用 JavaScript 解析 URL如何将 URL 解析为 Javascript 中的主机名和路径?用 JavaScript 或 jQuery 解析 URL。您怎么会错过那些呢?很抱歉,我必须投票将其关闭为重复项。


4
我不需要使用库。我知道有可用于解析URL的库,但我需要一个正则表达式。我所面临的情况是,我无法继续编写JavaScript代码。该函数需要将正则表达式、选项以及应用正则表达式的值作为参数,并返回第一个匹配项。 - sunilkumarba
我的意思是,我不能将JavaScript代码作为参数发送。我需要传递正则表达式。 - sunilkumarba
2
然后使用这个:var urlRegex ='^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$'; - user663031
4
这段代码不用于浏览器端,它是在node.js中使用的。是的,node.js有一个“url”模块可以使用。但很遗憾,由于之前提到的原因,我无法使用它。你的正则表达式已经处理了我们将要遇到的大多数URL类型。非常感谢。 - sunilkumarba
对于 Stack Overflow 来说,这个回答可能有点离题,但这个库救了我一命!谢谢。 - Peter Merkert
显示剩余2条评论

11

10
这里有一个解决方案,忽略://之前的所有内容。
.*\://?([^\/]+)

如果你想忽略www.

.*\://(?:www.)?([^\/]+)

好的。谢谢。但是,我还需要忽略掉“www.”这部分。我该怎么做? - sunilkumarba
所以,最终的正则表达式是 **.*://(?:www.)?([^/]+)**。 - sunilkumarba
1
“(?:www.)”后面的“?”有什么作用?我很好奇。顺便感谢您的帮助 :) - sunilkumarba
1
请查看此链接:http://www.regular-expressions.info/optional.html - Ashoka Lella

3
您的正则表达式已经很好了,您只需要去掉括号即可。最终的表达式是:
^(?:http:\/\/|www\.|https:\/\/)([^\/]+)

希望这对你有用!


2

这个使用命名捕获组的JavaScript正则表达式可以将链接/ URL分解为其功能组件:

console.log("https://www.sub.domain.google.com:443/maps/place/Arc+De+Triomphe/@48.8737917,2.2928388,17z?query=1&foo#hash".match(/^(?<protocol>https?:\/\/)(?=(?<fqdn>[^:/]+))(?:(?<service>www|ww\d|cdn|ftp|mail|pop\d?|ns\d?|git)\.)?(?:(?<subdomain>[^:/]+)\.)*(?<domain>[^:/]+\.[a-z0-9]+)(?::(?<port>\d+))?(?<path>\/[^?]*)?(?:\?(?<query>[^#]*))?(?:#(?<hash>.*))?/i).groups)

输出:

{
  "protocol": "https://",
  "fqdn": "www.sub.domain.google.com",
  "service": "www",
  "subdomain": "sub.domain",
  "domain": "google.com",
  "port": "443",
  "path": "/maps/place/Arc+De+Triomphe/@48.8737917,2.2928388,17z",
  "query": "query=1&foo",
  "hash": "hash"
}

所以您可以使用任何组件


0

我知道我来晚了,但我想回答这个问题并提供一些额外有用的信息。

使用正则表达式从链接中获取域名。

^(https?:\/\/)?(www\.)?([^\/]+)

这里是上面的正则表达式链接。

如果你想要获取子域名,可以使用上述正则表达式匹配结果中第一次出现.的位置进行split

注意:正则表达式比语言内置模块更快。请查看下面的示例,正则表达式比内置模块快15倍

JavaScript正则表达式示例:

console.time('time2');
const pttrn = /^(https?:\/\/)?(www\.)?([^\/]+)/gm
const urlInfo = pttrn.exec("https://www.google.co.in/imghp");
console.timeEnd('time2');

//time2: 0.055ms
console.log(urlInfo[0]) // https://www.google.co.in
console.log(urlInfo[1]) // https://
console.log(urlInfo[2]) // www.
console.log(urlInfo[3]) // google.co.in

具有内置url模块的Node.js

console.time('time');
const url = require('url');
const urlInfo = url.parse("https://www.google.co.in/imghp");
console.timeEnd('time');

//time: 0.840ms;
console.log(urlInfo.hostname) //www.google.co.in

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