获取URL的一部分(正则表达式)

pek*_*pek 127 regex language-agnostic url

给定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
Run Code Online (Sandbox Code Playgroud)

hom*_*ast 139

一个正则表达式来解析和分解一个完整的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,

主持人:正则表达式$ 3

路径:正则表达式$ 4

文件:正则表达式$ 6

查询:正则表达式$ 7,

哈希:正则表达式$ 8

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

什么会做的是使用这样的:

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

进一步解析"其余"尽可能具体.在一个正则表达式中执行它有点疯狂.

  • 问题是这一部分:`(.*)?`因为Kleene星已经接受0或更多,所以`?`部分(0或1)使它混淆.我通过将`(.*)?`改为`(.+)?`来修复它.你也可以删除`?` (19认同)
  • 并且证明没有正则表达式是完美的,这是一个立即修正:`^((http [s]?| ftp):\ /\/)?\ /?([^\/ \.] + \.)*?( [^\/ \] +\[^:\ /\S \.].{2,3}(\ [^:\ /\S \.].{2,3}))(?:\ d + ?)($ |????\ /)([^?#\ S] +)(*)(#\ W\ - ] +)$` (4认同)
  • 我修改了这个正则表达式来识别 URL 的所有部分(改进版本) - Python 中的代码 `^((?P<scheme>[^:/?#]+):(?=//))?(//) ?((((?P<登录>[^:]+)(?::(?P<密码>[^@]+)?)?@)?(?P<host>[^@/?#: ]*)(?::(?P<port>\d+)?)?)?(?P<path>[^?#]*)(\?(?P<query>[^#]*)) ?(#(?P<fragment>.*))?` `code` 你在 [pythex.org](https://pythex.org/) 上展示了这个代码 (4认同)
  • 链接http://codesnippets.joyent.com/posts/show/523自2010年10月20日起无效 (3认同)
  • 嗨Dve,我已经改进了一点,从像http://www.example.com:8080/....这样的网址中提取**example.com**.这里有:`^((http [ ?S] | FTP):\ /\/)\ /([^\/ \] + \)*([^\/ \] +\[^:\ /\S \?.?. ] {2,3}(\ [^:\ /\S \] {2,3}.)(:\ d +))($ |\/)([^#\ S] +)???? (#\ W\ - ] +)(.*?)?$` (3认同)
  • 我讨厌发布我也是的参考,但不是每个人都可以使用 python 正则表达式,并且之前发布的正则表达式不是与语言无关的,或者对于像 mailto:joe@someone.com 这样的 url 或经过完全身份验证的 URL 或没有尾部斜杠或包含类似 jim:bob@somewhere.com:8080 的端口。这个可以处理我能处理的所有事情。`^(([^@:\/\s]+):\/?)?\/?(([^@:\/\s]+)(:([^@:\/\s]+ ))?@)?([^@:\/\s]+)(:(\d+))?(((\/\w+)*\/)([\w\-\.]+[^ #?\s]*)?(.*)?(#[\w\-]+)?)?$` (2认同)

Rob*_*Rob 79

我意识到我迟到了,但有一种简单的方法让浏览器在没有正则表达式的情况下为你解析一个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
*/
Run Code Online (Sandbox Code Playgroud)

  • 鉴于原始问题被标记为"语言不可知",这是什么语言? (7认同)

gwg*_*gwg 58

我迟到了几年,但是我很惊讶没有人提到统一资源标识符规范有一节用正则表达式解析URI.伯纳斯 - 李等人撰写的正则表达式是:

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

上面第二行中的数字只是为了提高可读性; 它们表示每个子表达的参考点(即每个配对括号).我们将子表达式匹配的值称为$.例如,将上面的表达式与之匹配

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
Run Code Online (Sandbox Code Playgroud)

为了它的价值,我发现我必须在JavaScript中逃避正斜杠:

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

  • 很好的答案!从RFC中选择一些东西绝对不是坏事 (4认同)
  • 当协议隐含使用用户名/密码的 HTTP(我承认这是一种深奥且技术上无效的语法)时,它会中断:例如`user:pass@example.com` - RFC 3986 说:`包含冒号字符的路径段(例如,“this:that”)不能用作相对路径引用的第一段,因为它会被误认为是方案名称。这样的段前面必须有一个点段(例如,“./this:that”)以进行相对路径引用。` (3认同)
  • 这是最好的一面。具体来说,这解决了我在其他问题上遇到的两个问题:`1`:这可以正确处理其他协议,例如“ ftp://”和“ mailto://”。`2`:这可以正确处理`username`和`password`。这些可选字段由冒号分隔,就像主机名和端口一样,它将使我看到的大多数其他正则表达式失效。@RémyDAVID浏览器的location对象也不正常解析查询字符串。如果您需要解析查询字符串,请查看我的微型库:[uqs](https://npmjs.com/package/uqs)。 (2认同)
  • 这个答案值得更多的投票,因为它涵盖了几乎所有的协议. (2认同)

min*_*fai 31

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

  1. 它无法处理端口号.
  2. 哈希部分被破坏了.

以下是修改后的版本:

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

零件位置如下:

int SCHEMA = 2, DOMAIN = 3, PORT = 5, PATH = 6, FILE = 8, QUERYSTRING = 9, HASH = 12
Run Code Online (Sandbox Code Playgroud)

编辑由anon用户发布:

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

  • 请注意,如果 URL 域后没有路径,例如“http://www.example.com”,或者路径是单个字符(如“http://www.example”),则该方法不起作用.com/a`。 (2认同)

小智 11

我需要一个正则表达式来匹配所有网址并制作这个网址:

/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*)\.(?=[^\.\/\:]*\.[^\.\/\:]*))?([^\.\/\:]*)(?:\.([^\/\.\:]*))?(?:\:([0-9]*))?(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/
Run Code Online (Sandbox Code Playgroud)

它匹配所有网址,任何协议,甚至网址

ftp://user:pass@www.cs.server.com:8080/dir1/dir2/file.php?param1=value1#hashtag
Run Code Online (Sandbox Code Playgroud)

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

["ftp", "user", "pass", "www.cs", "server", "com", "8080", "/dir1/dir2/", "file.php", "param1=value1", "hashtag"]
Run Code Online (Sandbox Code Playgroud)

一个网址就像

mailto://admin@www.cs.server.com
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

["mailto", "admin", undefined, "www.cs", "server", "com", undefined, undefined, undefined, undefined, undefined] 
Run Code Online (Sandbox Code Playgroud)

  • 如果要匹配整个域/ IP地址(不用点分隔),请使用以下命令:`/(?:([[^ \:] *)\:\ / \ /)?(?:([^ \: \ @] *)(?:\:([^ \ @] *))?\ @)?(?:([^ \ / \:] *))?(?:\:([0-9] *))?\ /(\ / [^ \?#] *(?=。*?\ /)\ /)?([^ \?#] *)?(?:\?([^#] * ))((?:#(。*))?/` (2认同)

Sam*_*ams 8

我试图在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');
Run Code Online (Sandbox Code Playgroud)

因为(在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"
}
Run Code Online (Sandbox Code Playgroud)

然而,这不是跨浏览器(https://developer.mozilla.org/en-US/docs/Web/API/URL),所以我鹅卵石此一起拉如上出相同的部件:

^(?:(?:(([^:\/#\?]+:)?(?:(?:\/\/)(?:(?:(?:([^:@\/#\?]+)(?:\:([^:@\/#\?]*))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((?:\/?(?:[^\/\?#]+\/+)*)(?:[^\?#]*)))?(\?[^#]+)?)(#.*)?
Run Code Online (Sandbox Code Playgroud)

信用这个正则表达式去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
];
Run Code Online (Sandbox Code Playgroud)

还有一个小型库,它包装它并提供查询参数:

https://github.com/sadams/lite-url(也可在凉亭上使用)

如果你有改进,请创建一个带有更多测试的拉取请求,我将接受并合并谢谢.


oki*_*gan 6

提出一个更易读的解决方案(在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')
Run Code Online (Sandbox Code Playgroud)

打印:

{
'host': 'example.example.com', 
'user': None, 
'path': '/example/example/example.html', 
'query': None, 
'password': None, 
'port': None, 
'schema': 'http'
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ram 5

请尝试以下方法:

^((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+)*)?
Run Code Online (Sandbox Code Playgroud)

它支持HTTP/FTP,子域,文件夹,文件等.

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

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


tgm*_*dbm 5

子域和域很难,因为子域可以有几个部分,顶层域也可以,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://[^/]+/)  
Run Code Online (Sandbox Code Playgroud)

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

  • 非常有用-我添加了一个额外的`(http(s?):// [^ /] + /)`也可以获取https (2认同)

She*_*ore 5

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

   // 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'
   }
Run Code Online (Sandbox Code Playgroud)


igo*_*rzg 5

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");
Run Code Online (Sandbox Code Playgroud)

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

  • 这真太了不起了 (2认同)