【问题标题】:Getting parts of a URL (Regex)获取 URL 的一部分(正则表达式)
【发布时间】:2010-09-06 20:45:07
【问题描述】:

给定 URL(单行):
http://test.example.com/dir/subdir/file.html

如何使用正则表达式提取以下部分:

  1. 子域(测试)
  2. 域 (example.com)
  3. 没有文件的路径(/dir/subdir/)
  4. 文件 (file.html)
  5. 文件的路径 (/dir/subdir/file.html)
  6. 不带路径的 URL (http://test.example.com)
  7. (添加您认为有用的任何其他内容)

即使我输入以下 URL,正则表达式也应该可以正常工作:

http://example.example.com/example/example/example.html

【问题讨论】:

  • 这不是一个直接的答案,但大多数网络库都有完成此任务的功能。该函数通常被称为类似于CrackUrl。如果存在这样的功能,使用它,几乎可以保证它比任何手工编写的代码更可靠、更高效。
  • 请向我们解释为什么需要使用正则表达式来完成。如果是家庭作业,那就这么说吧,因为那是你的约束。否则,有比使用正则表达式更好的特定于语言的解决方案。
  • 第一个和最后一个示例的链接已损坏。
  • 这里您可以找到如何提取方案、域、TLD、端口和查询路径:stackoverflow.com/questions/9760588/…

标签: regex language-agnostic url


【解决方案1】:

一个正则表达式来解析和分解 包含查询参数的完整 URL 和锚点,例如

https://www.google.com/dir/1/2/search.html?arg=0-a&arg1=1-b&arg3-c#hash

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$

RexEx 职位:

url: 正则表达式['$&'],

协议:RegExp.$2,

主机:RegExp.$3,

路径:RegExp.$4,

文件:RegExp.$6,

查询:RegExp.$7,

hash:RegExp.$8

然后您可以很容易地进一步解析主机('.' 分隔)。

会做的是使用这样的东西:

/*
    ^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$
*/
proto $1
host $2
port $3
the-rest $4

进一步解析“其余部分”以尽可能具体。用一个正则表达式来做这件事有点疯狂。

【讨论】:

  • 链接 codesnippets.joyent.com/posts/show/523 自 2010 年 10 月 20 日起失效
  • 问题出在这部分:(.*)? 由于 Kleene 星已经接受 0 或更多,? 部分(0 或 1)会混淆它。我通过将(.*)? 更改为(.+)? 来修复它。您也可以删除 ?
  • 嗨,Dve,我对它进行了一些改进,可以从 http://www.example.com:8080/.... 等 URL 中提取 example.com 如下:^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?(:\d+)?)($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$
  • 并证明没有正则表达式是完美的,这里有一个立即更正:^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?)(:\d+)?($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$
  • 我修改了这个正则表达式以识别 URL 的所有部分(改进版本) - Python 中的代码 ^((?P<scheme>[^:/?#]+):(?=//))?(//)?(((?P<login>[^:]+)(?::(?P<password>[^@]+)?)?@)?(?P<host>[^@/?#:]*)(?::(?P<port>\d+)?)?)?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))? code 您在 pythex.org 上显示此代码的实际操作
【解决方案2】:

我意识到我迟到了,但是有一种简单的方法可以让浏览器在没有正则表达式的情况下为你解析一个 url:

var a = document.createElement('a');
a.href = 'http://www.example.com:123/foo/bar.html?fox=trot#foo';

['href','protocol','host','hostname','port','pathname','search','hash'].forEach(function(k) {
    console.log(k+':', a[k]);
});

/*//Output:
href: http://www.example.com:123/foo/bar.html?fox=trot#foo
protocol: http:
host: www.example.com:123
hostname: www.example.com
port: 123
pathname: /foo/bar.html
search: ?fox=trot
hash: #foo
*/

【讨论】:

  • 鉴于原始问题被标记为“与语言无关”,这是什么语言?
  • 请注意,此解决方案需要存在协议前缀,例如http://,才能正确显示协议、主机和主机名属性。否则 url 的开头直到第一个斜杠进入协议属性。
  • 我相信这个,虽然简单,但是比RegEx解析慢很多。
  • 所有浏览器都支持吗?
  • 如果我们这样做你也可以这样做var url = new URL(someUrl)
【解决方案3】:

我迟到了几年,但我很惊讶没有人提到统一资源标识符规范有 section on parsing URIs with a regular expression。 Berners-Lee 等人编写的正则表达式为:

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

上面第二行的数字只是为了便于阅读; 它们指示每个子表达式的参考点(即,每个 双括号)。我们指的是子表达式匹配的值 作为$。例如,将上面的表达式匹配到

http://www.ics.uci.edu/pub/ietf/uri/#Related

导致以下子表达式匹配:

$1 = http:
$2 = http
$3 = //www.ics.uci.edu
$4 = www.ics.uci.edu
$5 = /pub/ietf/uri/
$6 = <undefined>
$7 = <undefined>
$8 = #Related
$9 = Related

不管怎样,我发现我必须在 JavaScript 中转义正斜杠:

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

【讨论】:

  • 很好的答案!从 RFC 中选择一些东西肯定不会做错事
  • 这里不解析查询参数
  • 这是最好的一个。具体来说,这解决了我在其他协议中看到的两个问题:1:这可以正确处理其他协议,例如ftp://mailto://2:这可以正确处理usernamepassword。这些可选字段由冒号分隔,就像主机名和端口一样,它会触发我见过的大多数其他正则表达式。 @RémyDAVID 浏览器location 对象也无法正常解析查询字符串。如果您需要解析查询字符串,请查看我的小型库:uqs
  • 这个答案值得更多支持,因为它几乎涵盖了所有协议。
  • 当协议使用用户名/密码隐含 HTTP(我承认这是一种深奥且技术上无效的语法)时,它会中断:例如user:pass@example.com - RFC 3986 说:A path segment that contains a colon character (e.g., "this:that") cannot be used as the first segment of a relative-path reference, as it would be mistaken for a scheme name. Such a segment must be preceded by a dot-segment (e.g., "./this:that") to make a relative- path reference.
【解决方案4】:

我发现投票最高的答案(hometoast 的答案)对我来说并不完美。两个问题:

  1. 无法处理端口号。
  2. 哈希部分已损坏。

以下为修改版:

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$

零件位置如下:

int SCHEMA = 2, DOMAIN = 3, PORT = 5, PATH = 6, FILE = 8, QUERYSTRING = 9, HASH = 12

匿名用户发布的编辑:

function getFileName(path) {
    return path.match(/^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/[\w\/-]+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$/i)[8];
}

【讨论】:

  • 请注意,如果 URL 在域之后没有路径,则它不起作用 - 例如。 http://www.example.com 或者如果路径是单个字符,例如 http://www.example.com/a
【解决方案5】:

我需要一个正则表达式来匹配所有 url,并做了这个:

/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*)\.(?=[^\.\/\:]*\.[^\.\/\:]*))?([^\.\/\:]*)(?:\.([^\/\.\:]*))?(?:\:([0-9]*))?(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/

它匹配所有的 url,任何协议,甚至像这样的 url

ftp://user:pass@www.cs.server.com:8080/dir1/dir2/file.php?param1=value1#hashtag

结果(在 JavaScript 中)如下所示:

["ftp", "user", "pass", "www.cs", "server", "com", "8080", "/dir1/dir2/", "file.php", "param1=value1", "hashtag"]

类似的网址

mailto://admin@www.cs.server.com

看起来像这样:

["mailto", "admin", undefined, "www.cs", "server", "com", undefined, undefined, undefined, undefined, undefined] 

【讨论】:

  • 如果要匹配整个域/ip地址(不以点分隔)使用这个:/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*))?(?:\:([0-9]*))?\/(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/
【解决方案6】:

我试图在 javascript 中解决这个问题,应该由以下人员处理:

var url = new URL('http://a:b@example.com:890/path/wah@t/foo.js?foo=bar&bingobang=&king=kong@kong.com#foobar/bing/bo@ng?bang');

因为(至少在 Chrome 中)它解析为:

{
  "hash": "#foobar/bing/bo@ng?bang",
  "search": "?foo=bar&bingobang=&king=kong@kong.com",
  "pathname": "/path/wah@t/foo.js",
  "port": "890",
  "hostname": "example.com",
  "host": "example.com:890",
  "password": "b",
  "username": "a",
  "protocol": "http:",
  "origin": "http://example.com:890",
  "href": "http://a:b@example.com:890/path/wah@t/foo.js?foo=bar&bingobang=&king=kong@kong.com#foobar/bing/bo@ng?bang"
}

但是,这不是跨浏览器 (https://developer.mozilla.org/en-US/docs/Web/API/URL),所以我将其拼凑在一起,以提取与上述相同的部分:

^(?:(?:(([^:\/#\?]+:)?(?:(?:\/\/)(?:(?:(?:([^:@\/#\?]+)(?:\:([^:@\/#\?]*))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((?:\/?(?:[^\/\?#]+\/+)*)(?:[^\?#]*)))?(\?[^#]+)?)(#.*)?

这个正则表达式的功劳归于 https://gist.github.com/rpflorence,他发布了这个 jsperf http://jsperf.com/url-parsing(最初在这里找到:https://gist.github.com/jlong/2428561#comment-310066),他提出了这个最初基于的正则表达式。

零件顺序如下:

var keys = [
    "href",                    // http://user:pass@host.com:81/directory/file.ext?query=1#anchor
    "origin",                  // http://user:pass@host.com:81
    "protocol",                // http:
    "username",                // user
    "password",                // pass
    "host",                    // host.com:81
    "hostname",                // host.com
    "port",                    // 81
    "pathname",                // /directory/file.ext
    "search",                  // ?query=1
    "hash"                     // #anchor
];

还有一个封装了它并提供查询参数的小库:

https://github.com/sadams/lite-url(也可以在凉亭上找到)

如果您有改进,请创建一个包含更多测试的拉取请求,我会接受并合并,谢谢。

【讨论】:

  • 这很好,但确实可以使用像这样的版本来提取子域而不是重复的主机,主机名。因此,例如,如果我有 http://test1.dev.mydomain.com/,它将退出 test1.dev.
  • 这很好用。我一直在寻找一种从 url 中提取异常身份验证参数的方法,并且效果很好。
【解决方案7】:

子域和域很困难,因为子域可以有几个部分,顶级域http://sub1.sub2.domain.co.uk/也可以有几个部分

 the path without the file : http://[^/]+/((?:[^/]+/)*(?:[^/]+$)?)  
 the file : http://[^/]+/(?:[^/]+/)*((?:[^/.]+\.)+[^/.]+)$  
 the path with the file : http://[^/]+/(.*)  
 the URL without the path : (http://[^/]+/)  

(Markdown 对正则表达式不太友好)

【讨论】:

  • 非常有用 - 我添加了一个额外的 (http(s?)://[^/]+/) 来获取 https
【解决方案8】:

提出一个更具可读性的解决方案(在 Python 中,但适用于任何正则表达式):

def url_path_to_dict(path):
    pattern = (r'^'
               r'((?P<schema>.+?)://)?'
               r'((?P<user>.+?)(:(?P<password>.*?))?@)?'
               r'(?P<host>.*?)'
               r'(:(?P<port>\d+?))?'
               r'(?P<path>/.*?)?'
               r'(?P<query>[?].*?)?'
               r'$'
               )
    regex = re.compile(pattern)
    m = regex.match(path)
    d = m.groupdict() if m is not None else None

    return d

def main():
    print url_path_to_dict('http://example.example.com/example/example/example.html')

打印:

{
'host': 'example.example.com', 
'user': None, 
'path': '/example/example/example.html', 
'query': None, 
'password': None, 
'port': None, 
'schema': 'http'
}

【讨论】:

    【解决方案9】:

    这个改进的版本应该像解析器一样可靠。

       // Applies to URI, not just URL or URN:
       //    http://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Relationship_to_URL_and_URN
       //
       // http://labs.apache.org/webarch/uri/rfc/rfc3986.html#regexp
       //
       // (?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?
       //
       // http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax
       //
       // $@ matches the entire uri
       // $1 matches scheme (ftp, http, mailto, mshelp, ymsgr, etc)
       // $2 matches authority (host, user:pwd@host, etc)
       // $3 matches path
       // $4 matches query (http GET REST api, etc)
       // $5 matches fragment (html anchor, etc)
       //
       // Match specific schemes, non-optional authority, disallow white-space so can delimit in text, and allow 'www.' w/o scheme
       // Note the schemes must match ^[^\s|:/?#]+(?:\|[^\s|:/?#]+)*$
       //
       // (?:()(www\.[^\s/?#]+\.[^\s/?#]+)|(schemes)://([^\s/?#]*))([^\s?#]*)(?:\?([^\s#]*))?(#(\S*))?
       //
       // Validate the authority with an orthogonal RegExp, so the RegExp above won’t fail to match any valid urls.
       function uriRegExp( flags, schemes/* = null*/, noSubMatches/* = false*/ )
       {
          if( !schemes )
             schemes = '[^\\s:\/?#]+'
          else if( !RegExp( /^[^\s|:\/?#]+(?:\|[^\s|:\/?#]+)*$/ ).test( schemes ) )
             throw TypeError( 'expected URI schemes' )
          return noSubMatches ? new RegExp( '(?:www\\.[^\\s/?#]+\\.[^\\s/?#]+|' + schemes + '://[^\\s/?#]*)[^\\s?#]*(?:\\?[^\\s#]*)?(?:#\\S*)?', flags ) :
             new RegExp( '(?:()(www\\.[^\\s/?#]+\\.[^\\s/?#]+)|(' + schemes + ')://([^\\s/?#]*))([^\\s?#]*)(?:\\?([^\\s#]*))?(?:#(\\S*))?', flags )
       }
    
       // http://en.wikipedia.org/wiki/URI_scheme#Official_IANA-registered_schemes
       function uriSchemesRegExp()
       {
          return 'about|callto|ftp|gtalk|http|https|irc|ircs|javascript|mailto|mshelp|sftp|ssh|steam|tel|view-source|ymsgr'
       }
    

    【讨论】:

      【解决方案10】:

      尝试以下方法:

      ^((ht|f)tp(s?)\:\/\/|~/|/)?([\w]+:\w+@)?([a-zA-Z]{1}([\w\-]+\.)+([\w]{2,5}))(:[\d]{1,5})?((/?\w+/)+|/?)(\w+\.[\w]{3,4})?((\?\w+=\w+)?(&\w+=\w+)*)?
      

      支持HTTP/FTP、子域、文件夹、文件等

      我是通过谷歌快速搜索找到的:

      http://geekswithblogs.net/casualjim/archive/2005/12/01/61722.aspx

      【讨论】:

        【解决方案11】:
        /^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/
        

        来自我对similar question 的回答。比提到的其他一些更好,因为它们有一些错误(例如不支持用户名/密码,不支持单字符文件名,片段标识符被破坏)。

        【讨论】:

          【解决方案12】:
          const URI_RE = /^(([^:\/\s]+):\/?\/?([^\/\s@]*@)?([^\/@:]*)?:?(\d+)?)?(\/[^?]*)?(\?([^#]*))?(#[\s\S]*)?$/;
          /**
          * GROUP 1 ([scheme][authority][host][port])
          * GROUP 2 (scheme)
          * GROUP 3 (authority)
          * GROUP 4 (host)
          * GROUP 5 (port)
          * GROUP 6 (path)
          * GROUP 7 (?query)
          * GROUP 8 (query)
          * GROUP 9 (fragment)
          */
          URI_RE.exec("https://john:doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top");
          URI_RE.exec("/forum/questions/?tag=networking&order=newest#top");
          URI_RE.exec("ldap://[2001:db8::7]/c=GB?objectClass?one");
          URI_RE.exec("mailto:John.Doe@example.com");
          

          您可以在上面找到使用修改过的正则表达式的 javascript 实现

          【讨论】:

          • 这太棒了
          【解决方案13】:

          您可以使用.NET 中的Uri 对象获取所有http/https、主机、端口、路径以及查询。 只是困难的任务是将主机分解为子域,域名和TLD。

          这样做没有标准,不能简单地使用字符串解析或正则表达式来产生正确的结果。起初,我使用的是 RegEx 函数,但并非所有 URL 都可以正确解析子域。实践方法是使用 TLD 列表。定义 URL 的 TLD 后,左侧部分是域,其余部分是子域。

          但是,由于可以使用新的 TLD,因此需要维护该列表。我知道的当前时刻是publicsuffix.org维护最新列表,您可以使用google代码中的域名解析器工具来解析公共后缀列表并通过使用DomainName对象轻松获取子域、域和TLD:domainName.SubDomain, domainName .Domain 和 domainName.TLD。

          这个答案也很有帮助: Get the subdomain from a URL

          CaLLMeLaNN

          【讨论】:

            【解决方案14】:

            这里是完整的,不依赖任何协议。

            function getServerURL(url) {
                    var m = url.match("(^(?:(?:.*?)?//)?[^/?#;]*)");
                    console.log(m[1]) // Remove this
                    return m[1];
                }
            
            getServerURL("http://dev.test.se")
            getServerURL("http://dev.test.se/")
            getServerURL("//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js")
            getServerURL("//")
            getServerURL("www.dev.test.se/sdas/dsads")
            getServerURL("www.dev.test.se/")
            getServerURL("www.dev.test.se?abc=32")
            getServerURL("www.dev.test.se#abc")
            getServerURL("//dev.test.se?sads")
            getServerURL("http://www.dev.test.se#321")
            getServerURL("http://localhost:8080/sads")
            getServerURL("https://localhost:8080?sdsa")
            

            印刷品

            http://dev.test.se
            
            http://dev.test.se
            
            //ajax.googleapis.com
            
            //
            
            www.dev.test.se
            
            www.dev.test.se
            
            www.dev.test.se
            
            www.dev.test.se
            
            //dev.test.se
            
            http://www.dev.test.se
            
            http://localhost:8080
            
            https://localhost:8080
            

            【讨论】:

              【解决方案15】:

              以上都不适合我。这是我最终使用的:

              /^(?:((?:https?|s?ftp):)\/\/)([^:\/\s]+)(?::(\d*))?(?:\/([^\s?#]+)?([?][^?#]*)?(#.*)?)?/
              

              【讨论】:

                【解决方案16】:

                我喜欢“Javascript: The Good Parts”中发布的正则表达式。 它不太短,也不太复杂。 github 上的这个页面也有使用它的 JavaScript 代码。 但它适用于任何语言。 https://gist.github.com/voodooGQ/4057330

                【讨论】:

                  【解决方案17】:

                  Java 提供了一个 URL 类来执行此操作。 Query URL Objects.

                  附带说明,PHP 提供parse_url()

                  【讨论】:

                  • 看起来这并没有解析出子域?
                  • 询问者要求使用正则表达式。 URL 类将在您创建它时打开一个连接。
                  • "URL 类会在你创建它时打开一个连接" - 这是不正确的,只有当你调用 connect() 之类的方法时。但确实 java.net.URL 有点重。对于这个用例,java.net.URI 更好。
                  【解决方案18】:

                  我建议不要使用正则表达式。像 WinHttpCrackUrl() 这样的 API 调用更不容易出错。

                  http://msdn.microsoft.com/en-us/library/aa384092%28VS.85%29.aspx

                  【讨论】:

                  • 而且还非常特定于平台。
                  • 我认为重点是使用库,而不是重新发明轮子。 Ruby、Python、Perl 有工具可以拆分 URL,因此请抓住这些工具而不是实现错误的模式。
                  【解决方案19】:

                  我尝试了其中一些不能满足我需求的方法,尤其是投票最高的那些没有捕获没有路径的 url (http://example.com/)

                  还缺少组名使其无法在 ansible 中使用(或者可能是我的 jinja2 技能不足)。

                  所以这是我稍微修改的版本,源是这里投票最高的版本:

                  ^((?P<protocol>http[s]?|ftp):\/)?\/?(?P<host>[^:\/\s]+)(?P<path>((\/\w+)*\/)([\w\-\.]+[^#?\s]+))*(.*)?(#[\w\-]+)?$
                  

                  【讨论】:

                    【解决方案20】:

                    我建造了这个。非常宽容,不检查url只是划分它。

                    ^((http[s]?):\/\/)?([a-zA-Z0-9-.]*)?([\/]?[^?#\n]*)?([?]?[^?#\n]*)?([#]?[^?#\n]*)$

                    • 匹配 1:带有 ://(http 或 https)的完整协议
                    • 匹配 2:没有 ://
                    • 的协议
                    • 匹配 3:主机
                    • 匹配 4:蛞蝓
                    • 匹配 5:参数
                    • 匹配 6:锚

                    工作

                    http://
                    https://
                    www.demo.com
                    /slug
                    ?foo=bar
                    #anchor
                    
                    https://demo.com
                    https://demo.com/
                    https://demo.com/slug
                    https://demo.com/slug/foo
                    https://demo.com/?foo=bar
                    https://demo.com/?foo=bar#anchor
                    https://demo.com/?foo=bar&bar=foo#anchor
                    https://www.greate-demo.com/
                    

                    崩溃

                    #anchor#
                    ?toto?
                    

                    【讨论】:

                      【解决方案21】:

                      我需要一些正则表达式来解析 Java 中 URL 的组成部分。 这是我正在使用的:

                      "^(?:(http[s]?|ftp):/)?/?" +    // METHOD
                      "([^:^/^?^#\\s]+)" +            // HOSTNAME
                      "(?::(\\d+))?" +                // PORT
                      "([^?^#.*]+)?" +                // PATH
                      "(\\?[^#.]*)?" +                // QUERY
                      "(#[\\w\\-]+)?$"                // ID
                      

                      Java 代码片段:

                      final Pattern pattern = Pattern.compile(
                              "^(?:(http[s]?|ftp):/)?/?" +    // METHOD
                              "([^:^/^?^#\\s]+)" +            // HOSTNAME
                              "(?::(\\d+))?" +                // PORT
                              "([^?^#.*]+)?" +                // PATH
                              "(\\?[^#.]*)?" +                // QUERY
                              "(#[\\w\\-]+)?$"                // ID
                      );
                      final Matcher matcher = pattern.matcher(url);
                      
                      System.out.println("     URL: " + url);
                      
                      if (matcher.matches())
                      {
                          System.out.println("  Method: " + matcher.group(1));
                          System.out.println("Hostname: " + matcher.group(2));
                          System.out.println("    Port: " + matcher.group(3));
                          System.out.println("    Path: " + matcher.group(4));
                          System.out.println("   Query: " + matcher.group(5));
                          System.out.println("      ID: " + matcher.group(6));
                          
                          return matcher.group(2);
                      }
                      
                      System.out.println();
                      System.out.println();
                      

                      【讨论】:

                      • 主机正则表达式在字符串 saas-dev.com 上失败。返回的匹配是aa-dev.com。我使用RegExr 进行测试。
                      【解决方案22】:

                      使用http://www.fileformat.info/tool/regex.htm hometoast 的正则表达式效果很好。

                      但这是交易,我想在我的程序中的不同情况下使用不同的正则表达式模式。

                      例如,我有这个 URL,我有一个枚举,列出了我的程序中所有支持的 URL。枚举中的每个对象都有一个 getRegexPattern 方法,该方法返回正则表达式模式,然后将使用该模式与 URL 进行比较。如果特定的正则表达式模式返回 true,那么我知道我的程序支持此 URL。因此,每个枚举都有自己的正则表达式,具体取决于它在 URL 中的位置。

                      Hometoast 的建议很棒,但就我而言,我认为它无济于事(除非我在所有枚举中复制粘贴相同的正则表达式)。

                      这就是为什么我希望答案分别针对每种情况给出正则表达式。虽然 +1 是家庭吐司。 ;)

                      【讨论】:

                        【解决方案23】:

                        我知道您在这方面声称与语言无关,但您能否告诉我们您使用的是什么,以便我们知道您拥有哪些正则表达式功能?

                        如果您有非捕获匹配的能力,您可以修改 hometoast 的表达式,以便您不感兴趣捕获的子表达式设置如下:

                        (?:SOMESTUFF)

                        您仍然需要将正则表达式复制并粘贴(并稍微修改)到多个位置,但这是有道理的——您不仅要检查子表达式是否存在,还要检查它是否存在 作为 URL 的一部分。对子表达式使用 non-capturing 修饰符可以满足您的需求,仅此而已,如果我没看错的话,这就是您想要的。

                        就像一个小小的注释一样,hometoast 的表达式不需要在“https”的“s”周围加上括号,因为他只有一个字符。量词量化直接在它们之前的一个字符(或字符类或子表达式)。所以:

                        https?

                        匹配 'http' 或 'https' 就好了。

                        【讨论】:

                          【解决方案24】:

                          regexp 获取不带文件的 URL 路径。

                          url = 'http://domain/dir1/dir2/somefile' url.scan(/^(http://[^/]+)((?:/[^/]+)+(?=/))?/?(?:[^/]+)?$/ i).to_s

                          添加到这个 url 的相对路径很有用。

                          【讨论】:

                            【解决方案25】:

                            进行完整解析的正则表达式非常可怕。为了便于阅读,我已经包含了命名的反向引用,并将每个部分分成单独的行,但它仍然看起来像这样:

                            ^(?:(?P<protocol>\w+(?=:\/\/))(?::\/\/))?
                            (?:(?P<host>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::(?P<port>[0-9]+))?)\/)?
                            (?:(?P<path>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?
                            (?P<file>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)
                            (?:\?(?P<querystring>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?
                            (?:#(?P<fragment>.*))?$
                            

                            要求它如此冗长的是,除了协议或端口之外,任何部分都可以包含 HTML 实体,这使得片段的描述非常棘手。所以在最后几种情况下——主机、路径、文件、查询字符串和片段,我们允许任何 html 实体或任何不是?# 的字符。 html 实体的正则表达式如下所示:

                            $htmlentity = "&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);"
                            

                            当它被提取出来时(我用小胡子语法来表示它),它变得更清晰了:

                            ^(?:(?P<protocol>(?:ht|f)tps?|\w+(?=:\/\/))(?::\/\/))?
                            (?:(?P<host>(?:{{htmlentity}}|[^\/?#:])+(?::(?P<port>[0-9]+))?)\/)?
                            (?:(?P<path>(?:{{htmlentity}}|[^?#])+)\/)?
                            (?P<file>(?:{{htmlentity}}|[^?#])+)
                            (?:\?(?P<querystring>(?:{{htmlentity}};|[^#])+))?
                            (?:#(?P<fragment>.*))?$
                            

                            在 JavaScript 中,当然不能使用命名反向引用,所以正则表达式变成了

                            ^(?:(\w+(?=:\/\/))(?::\/\/))?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::([0-9]+))?)\/)?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)(?:\?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?(?:#(.*))?$
                            

                            在每个匹配项中,协议是\1,主机是\2,端口是\3,路径是\4,文件是\5,查询字符串是\6,以及片段\7.

                            【讨论】:

                              【解决方案26】:
                              //USING REGEX
                              /**
                               * Parse URL to get information
                               *
                               * @param   url     the URL string to parse
                               * @return  parsed  the URL parsed or null
                               */
                              var UrlParser = function (url) {
                                  "use strict";
                              
                                  var regx = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
                                      matches = regx.exec(url),
                                      parser = null;
                              
                                  if (null !== matches) {
                                      parser = {
                                          href              : matches[0],
                                          withoutHash       : matches[1],
                                          url               : matches[2],
                                          origin            : matches[3],
                                          protocol          : matches[4],
                                          protocolseparator : matches[5],
                                          credhost          : matches[6],
                                          cred              : matches[7],
                                          user              : matches[8],
                                          pass              : matches[9],
                                          host              : matches[10],
                                          hostname          : matches[11],
                                          port              : matches[12],
                                          pathname          : matches[13],
                                          segment1          : matches[14],
                                          segment2          : matches[15],
                                          search            : matches[16],
                                          hash              : matches[17]
                                      };
                                  }
                              
                                  return parser;
                              };
                              
                              var parsedURL=UrlParser(url);
                              console.log(parsedURL);
                              

                              【讨论】:

                                【解决方案27】:

                                我试过这个正则表达式来解析 url 分区:

                                ^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*))(\?([^#]*))?(#(.*))?$
                                

                                网址:https://www.google.com/my/path/sample/asd-dsa/this?key1=value1&amp;key2=value2

                                匹配:

                                Group 1.    0-7 https:/
                                Group 2.    0-5 https
                                Group 3.    8-22    www.google.com
                                Group 6.    22-50   /my/path/sample/asd-dsa/this
                                Group 7.    22-46   /my/path/sample/asd-dsa/
                                Group 8.    46-50   this
                                Group 9.    50-74   ?key1=value1&key2=value2
                                Group 10.   51-74   key1=value1&key2=value2
                                

                                【讨论】:

                                  【解决方案28】:

                                  这里建议的最佳答案对我不起作用,因为我的 URL 还包含一个端口。 但是将其修改为以下正则表达式对我有用:

                                  ^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:\d+)?((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$
                                  

                                  【讨论】:

                                    【解决方案29】:

                                    对于浏览器/nodejs 环境,有一个内置的 URL 类,它似乎共享相同的签名。但请查看您的案例的相应重点。

                                    https://nodejs.org/api/url.html#urlhost

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

                                    这就是它的使用方式。

                                    let url = new URL('https://test.example.com/cats?name=foofy')
                                    url.protocall; // https:
                                    url.hostname; // test.example.com
                                    url.pathname; // /cats
                                    url.search; // ?name=foofy
                                    
                                    let params = url.searchParams
                                    let name = params.get('name');// always string I think so parse accordingly
                                    
                                    

                                    更多参数见https://developer.mozilla.org/en-US/docs/Web/API/URL/searchParams

                                    【讨论】:

                                      【解决方案30】:
                                      String s = "https://www.thomas-bayer.com/axis2/services/BLZService?wsdl";
                                      
                                      String regex = "(^http.?://)(.*?)([/\\?]{1,})(.*)";
                                      
                                      System.out.println("1: " + s.replaceAll(regex, "$1"));
                                      System.out.println("2: " + s.replaceAll(regex, "$2"));
                                      System.out.println("3: " + s.replaceAll(regex, "$3"));
                                      System.out.println("4: " + s.replaceAll(regex, "$4"));
                                      

                                      将提供以下输出:
                                      1:https://
                                      2: www.thomas-bayer.com
                                      3:/
                                      4:axis2/services/BLZService?wsdl

                                      如果您将 URL 更改为
                                      字符串 s = "https://www.thomas-bayer.com?wsdl=qwerwer&ttt=888"; 输出将如下:
                                      1:https://
                                      2: www.thomas-bayer.com
                                      3:?
                                      4:wsdl=qwerwer&ttt=888

                                      享受..
                                      尤西列夫

                                      【讨论】:

                                      • 不处理端口。语言不可知论。
                                      猜你喜欢
                                      • 2014-09-04
                                      • 1970-01-01
                                      • 2016-12-27
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2017-10-23
                                      • 2018-08-18
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多