我想匹配的只是一个URL的根,而不是一个文本字符串的整个URL。考虑到:

http://www.youtube.com/watch?v=ClkQA2Lb_iE
http://youtu.be/ClkQA2Lb_iE
http://www.example.com/12xy45
http://example.com/random

我想让最后2个实例解析到www.example.com或example.com域。

我听说正则表达式很慢,这将是我在页面上的第二个正则表达式,所以如果有办法做到没有正则表达式,请告诉我。

我正在寻找这个解决方案的JS/jQuery版本。


当前回答

代码:

var regex = /\w+.(com|co\.kr|be)/ig;
var urls = ['http://www.youtube.com/watch?v=ClkQA2Lb_iE',
            'http://youtu.be/ClkQA2Lb_iE',
            'http://www.example.com/12xy45',
            'http://example.com/random'];


$.each(urls, function(index, url) {
    var convertedUrl = url.match(regex);
    console.log(convertedUrl);
});

结果:

youtube.com
youtu.be
example.com
example.com

其他回答

试试这个:

var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
var domain = matches && matches[1];  // domain will be null if no match is found

如果你想从结果中排除端口,请使用下面的表达式:

/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i

编辑:要防止特定域匹配,请使用反向前向。(? ! youtube.com)

/^https?\:\/\/(?!(?:www\.)?(?:youtube\.com|youtu\.be))([^\/:?#]+)(?:[\/:?#]|$)/i

只需使用URL()构造函数:

new URL(url).host
// use this if you know you have a subdomain
// www.domain.com -> domain.com
function getDomain() {
  return window.location.hostname.replace(/([a-zA-Z0-9]+.)/,"");
}

我给你3个可能的解决方案:

使用npm包psl提取你扔给它的任何东西。 使用我的自定义实现extractRootDomain,它适用于大多数情况。 网址(URL)。主机名是可行的,但并非适用于所有边缘情况。点击“运行代码段”查看它是如何运行的。

1. 使用npm包psl(公共后缀列表)

“公共后缀列表”是所有有效域名后缀和规则的列表,不仅是国家代码顶级域名,还包括被视为根域的unicode字符(即www.食狮.公司.cn, b.c.a bebe .jp等)。点击这里阅读更多信息。

Try:

npm install --save psl

然后用我的“extractHostname”实现运行:

let psl = require('psl');
let url = 'http://www.youtube.com/watch?v=ClkQA2Lb_iE';
psl.get(extractHostname(url)); // returns youtube.com

2. extractRootDomain的自定义实现

下面是我的实现,它还针对各种可能的URL输入运行。

function extractHostname(url) { var hostname; //find & remove protocol (http, ftp, etc.) and get hostname if (url.indexOf("//") > -1) { hostname = url.split('/')[2]; } else { hostname = url.split('/')[0]; } //find & remove port number hostname = hostname.split(':')[0]; //find & remove "?" hostname = hostname.split('?')[0]; return hostname; } // Warning: you can use this function to extract the "root" domain, but it will not be as accurate as using the psl package. function extractRootDomain(url) { var domain = extractHostname(url), splitArr = domain.split('.'), arrLen = splitArr.length; //extracting the root domain here //if there is a subdomain if (arrLen > 2) { domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]; //check to see if it's using a Country Code Top Level Domain (ccTLD) (i.e. ".me.uk") if (splitArr[arrLen - 2].length == 2 && splitArr[arrLen - 1].length == 2) { //this is using a ccTLD domain = splitArr[arrLen - 3] + '.' + domain; } } return domain; } const urlHostname = url => { try { return new URL(url).hostname; } catch(e) { return e; } }; const urls = [ "http://www.blog.classroom.me.uk/index.php", "http://www.youtube.com/watch?v=ClkQA2Lb_iE", "https://www.youtube.com/watch?v=ClkQA2Lb_iE", "www.youtube.com/watch?v=ClkQA2Lb_iE", "ftps://ftp.websitename.com/dir/file.txt", "websitename.com:1234/dir/file.txt", "ftps://websitename.com:1234/dir/file.txt", "example.com?param=value", "https://facebook.github.io/jest/", "//youtube.com/watch?v=ClkQA2Lb_iE", "www.食狮.公司.cn", "b.c.kobe.jp", "a.d.kyoto.or.jp", "http://localhost:4200/watch?v=ClkQA2Lb_iE" ]; const test = (method, arr) => console.log( `=== Testing "${method.name}" ===\n${arr.map(url => method(url)).join("\n")}\n`); test(extractHostname, urls); test(extractRootDomain, urls); test(urlHostname, urls);

无论是否有协议或端口号,您都可以提取域。这是一个非常简化的,非正则表达式的解,所以我认为这可以解决我们在问题中提供的数据集。

3. 网址(URL) hostname

网址(URL)。主机名是一个有效的解决方案,但它不适用于我已经解决的一些边缘情况。正如您在上次测试中看到的,它不喜欢某些url。你绝对可以使用我的解决方案的组合来让它全部工作。

*感谢@Timmerz, @renoirb, @rineez, @BigDong, @ra00l, @ILikeBeansTacos, @CharlesRobertson的建议!@ross-allen,谢谢你报告这个bug!

import URL from 'url';

const pathname = URL.parse(url).path;
console.log(url.replace(pathname, ''));

这样就兼顾了协议。