如何解析一个 URL?

IT技术 javascript regex
2021-01-28 17:32:34

如果有一件事我无法理解,那就是正则表达式。

因此,经过大量搜索,我终于找到了适合我的需求:

function get_domain_name()
    { 
    aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
    //aaaa="http://somesite.se/blah/sese";
        domain_name_parts = aaaa.match(/:\/\/(.[^/]+)/)[1].split('.');
        if(domain_name_parts.length >= 3){
            domain_name_parts[0] = '';
        }
        var domain = domain_name_parts.join('.');
        if(domain.indexOf('.') == 0)
            alert("1"+ domain.substr(1));
        else
            alert("2"+ domain);
    }

它基本上给了我域名,反正我也可以得到域名后的所有东西吗?在这种情况下,它将/blah/sdgsdgsdgs来自aaaa变量。

6个回答

编辑(2020 年):在现代浏览器中,您可以使用内置的URLWeb API。

https://developer.mozilla.org/en-US/docs/Web/API/URL/URL

var url = new URL("http://www.somesite.se/blah/sdgsdgsdgs");
var pathname = url.pathname; // returns /blah/sdgsdgsdgs

您应该使用 JavaScript DOM API 提供的内置 URL 解析器,而不是依赖可能不可靠的*正则表达式:

var url = document.createElement('a');
url.href = "http://www.example.com/some/path?name=value#anchor";

这就是解析 URL 所需要做的全部工作。其他一切都只是访问解析的值:

url.protocol; //(http:)
url.hostname; //(www.example.com)
url.pathname; //(/some/path)
url.search; // (?name=value)
url.hash; //(#anchor)

在这种情况下,如果您正在寻找/blah/sdgsdgsdgs,则可以使用url.pathname

基本上,您只是在 JavaScript 中创建一个链接(技术上,锚元素),然后您可以直接调用已解析的片段。(因为您没有将它添加到 DOM,它不会在任何地方添加任何不可见的链接。)它的访问方式与location对象上的值相同

(受到这个精彩答案的启发。)

编辑:一个重要的注意事项:Internet Explorer 似乎有一个错误,它省略了pathname像这样的对象属性上的前导斜杠您可以通过执行以下操作对其进行标准化:

 url.pathname = url.pathname.replace(/(^\/?)/,"/");

注意:*:我说“可能不可靠”,因为尝试构建或找到一个包罗万象的 URL 解析器可能很诱人,但是有很多很多条件、边缘情况和宽容的解析技术可能不被考虑或正确支持的; 浏览器可能最擅长实现(因为解析 URL 对它们的正确操作至关重要)这个逻辑,所以我们应该保持简单并将它留给他们。

一个有value的脚注:我发现这不是一个好方法的唯一一次是,如果您正在解析大量链接;DOM 元素创建比正则表达式更昂贵。在少数情况下,差异无法区分。在 100+ 时,它可以产生明显的效果。
2021-03-24 17:32:34
很好地呼吁规范化pathname您确定重新分配归一化没有副作用pathname吗?另外,我可以建议()从正则表达式中删除吗?
2021-04-01 17:32:34
将这项工作交给浏览器就像:我希望浏览器能正确执行……如您所提到的,IE 错误可能是一个问题
2021-04-08 17:32:34
该代码是否包含在 JavaScript DOM 绑定标准中?- 我还没找到。
2021-04-14 17:32:34

RFC(见附录B)提供一个正则表达式来解析URI部分:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 12            3  4          5       6  7        8 9

在哪里

scheme    = $2
authority = $4
path      = $5
query     = $7
fragment  = $9

例子:

function parse_url(url) {
    var pattern = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
    var matches =  url.match(pattern);
    return {
        scheme: matches[2],
        authority: matches[4],
        path: matches[5],
        query: matches[7],
        fragment: matches[9]
    };
}
console.log(parse_url("http://www.somesite.se/blah/sdgsdgsdgs"));

Object
    authority: "www.somesite.se"
    fragment: undefined
    path: "/blah/sdgsdgsdgs"
    query: undefined
    scheme: "http"

演示

另外我想补充一下,如何获取当前 URI:document.URL以及如何解析查询:stackoverflow.com/a/2091331/1069083
2021-03-17 17:32:34
我想我必须先正确学习正则表达式才能理解你的帖子伙伴,尽管我确信它非常有帮助。
2021-03-23 17:32:34
您可以使用非捕获组来增强正则表达式。
2021-03-27 17:32:34
这是毒品啊!感谢您链接 RFC。真正的英雄,那些作者。
2021-04-07 17:32:34
对于非捕获组:"^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(\\?(?:[^#]*))?(#(?:.*))?". 仅返回方案、主机、路径、查询和片段。注意:://不是方案的一部分,因为方案实际上可以省略。
2021-04-09 17:32:34

请注意,此解决方案不是最好的。我这样做只是为了符合 OP 的要求。我个人建议查看其他答案。

以下正则表达式将返回域和其余部分。:\/\/(.[^\/]+)(.*)

  1. www.google.com
  2. /goosomething

我建议你在这里学习 RegExp 文档:http : //www.regular-expressions.info/reference.html

使用您的功能:

function get_domain_name()
    { 
    aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
    //aaaa="http://somesite.se/blah/sese";
        var matches = aaaa.match(/:\/\/(?:www\.)?(.[^/]+)(.*)/);
        alert(matches[1]);
        alert(matches[2]);
    }
可以提醒(匹配 [1]);不带“www.”就返回它?警报(匹配 [2]);是完美的!并感谢您的链接。
2021-03-22 17:32:34
@kuroir 不能将“已接受”的解决方案重新设置为得票最多的解决方案吗?我很确定你可以做到...
2021-04-02 17:32:34
正是我所要求的,特别感谢!(也谢谢大家的回复!)
2021-04-06 17:32:34

你只需要稍微修改你的正则表达式。例如:

var aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
var m = aaaa.match(/^[^:]*:\/\/([^\/]+)(\/.*)$/);

m 将包含以下部分:

["http://www.somesite.se/blah/sdgsdgsdgs", "www.somesite.se", "/blah/sdgsdgsdgs"]

这是相同的示例,但进行了修改,以便将“www”分开。部分。我认为应该编写正则表达式,以便无论您是否拥有“www”,匹配都将起作用。部分。所以看看这个:

var aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
var m = aaaa.match(/^[^:]*:\/\/(www\.)?([^\/]+)(\/.*)$/);

m 将包含以下部分:

["http://www.somesite.se/blah/sdgsdgsdgs", "www.", "somesite.se", "/blah/sdgsdgsdgs"]

现在检查相同的正则表达式,但网址不以“www.”开头:

var bbbb="http://somesite.se/blah/sdgsdgsdgs";
var m = .match(/^[^:]*:\/\/(www\.)?([^\/]+)(\/.*)$/);

现在你的比赛看起来像这样:

["http://somesite.se/blah/sdgsdgsdgs", undefined, "somesite.se", "/blah/sdgsdgsdgs"]

因此,如您所见,它在两种情况下都会做正确的事情。

编辑; 我的意思是:不,我需要第二部分没有“www”。和原版一模一样。你上面写的第三部分是完美的。谢谢!
2021-03-22 17:32:34
嘿!感谢回复!不,我需要第二部分没有“www”。和原版一模一样。第二部分就像你上面写的那样。谢谢!
2021-04-04 17:32:34

有一个很好的 jQuery 插件用于解析 URL:Purl

所有正则表达式的东西都隐藏在里面,你会得到类似的东西:

> url = $.url("http://markdown.com/awesome/language/markdown.html?show=all#top");

> url.attr('source');
"http://markdown.com/awesome/language/markdown.html?show=all#top"

> url.attr('protocol');
"http"

> url.attr('host');
"markdown.com"

> url.attr('relative');
"/awesome/language/markdown.html?show=all#top"

> url.attr('path');
"/awesome/language/markdown.html"

> url.attr('directory');
"/awesome/language/"

> url.attr('file');
"markdown.html"

> url.attr('query');
"show=all"

> url.attr('fragment');
"top"