从URL中提取正则表达式URL路径

25

我在处理正则表达式时遇到一些问题。

我正在尝试从此URL中获取路径videoplay

http://video.google.co.uk:80/videoplay?docid=-7246927612831078230&hl=en#hello
如果我使用这个正则表达式 /.+,它也会匹配到 /video
我需要一种反向/负向匹配,以便不包括//

1
当我需要快速使用正则表达式处理URL时,通常在捕获组之前在开头加上//。请注意不能使用http://,因为它们可能使用不同的协议进行访问,甚至也不能使用://,因为它们可能会指定端口号。 - jwrush
可能是[获取URL的部分(正则表达式)]的重复问题(https://dev59.com/H3VD5IYBdhLWcg3wTJrF)。 - Raniz
13个回答

45

如果您需要在JavaScript Web应用程序中使用此代码,请参考此主题中我找到的最佳答案here。 代码的基本(以及原始)版本如下:

var parser = document.createElement('a');
parser.href = "http://example.com:3000/pathname/?search=test#hash";

parser.protocol; // => "http:"
parser.hostname; // => "example.com"
parser.port;     // => "3000"
parser.pathname; // => "/pathname/"
parser.search;   // => "?search=test"
parser.hash;     // => "#hash"
parser.host;     // => "example.com:3000"

谢谢John Long,你让我的一天美好了!


16

2
如果路径为 www.abc.com?param=xyz 这样的话,就无法正常工作了。我稍微修改了一下,使它可以正常工作(同时在前两个组中使用了非匹配组)。修改后的正则表达式如下: (?:https?:\/\/)?(?:[^?\/\s]+[?\/])(.*) 示例:https://regex101.com/r/eNUBb9 - nbeuchat

10

这个表达式获取videoplay之后的所有内容,也就是URL路径。

/\/(videoplay.+)/

这个表达式获取端口后面的所有内容,也包括路径。

/\:\d./(.+)/

然而,如果使用Node.js,我建议使用原生的url模块。
var url = require('url')
var youtubeUrl = "http://video.google.co.uk:80/videoplay?docid=-7246927612831078230&hl=en#hello"
url.parse(youtubeUrl)

这个工具可以帮助你完成所有的正则表达式工作。

{
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'video.google.co.uk:80',
  port: '80',
  hostname: 'video.google.co.uk',
  hash: '#hello',
  search: '?docid=-7246927612831078230&hl=en',
  query: 'docid=-7246927612831078230&hl=en',
  pathname: '/videoplay',
  path: '/videoplay?docid=-7246927612831078230&hl=en',
  href: 'http://video.google.co.uk:80/videoplay?docid=-7246927612831078230&hl=en#hello' 
}

url 节点模块处于遗留模式。文档建议使用 URL 类代替。请参见此处:https://nodejs.org/dist/latest-v14.x/docs/api/url.html#url_legacy_url_api - darksinge

5

function getPath(url, defaults){
    var reUrlPath = /(?:\w+:)?\/\/[^\/]+([^?#]+)/;
    var urlParts = url.match(reUrlPath) || [url, defaults];
    return urlParts.pop();
}
alert( getPath('https://dev59.com/L3VD5IYBdhLWcg3wXamd/regex-url', 'unknown') );
alert( getPath('https://dev59.com/L3VD5IYBdhLWcg3wXamd/regex-url', 'unknown') );
alert( getPath('//stackoverflow.com/q/123/regex-url', 'unknown') );
alert( getPath('https://dev59.com/L3VD5IYBdhLWcg3wXamd/regex-url?foo', 'unknown') );
alert( getPath('https://dev59.com/L3VD5IYBdhLWcg3wXamd/regex-url#foo', 'unknown') );
alert( getPath('https://dev59.com/L3VD5IYBdhLWcg3wXamd/regex-url/', 'unknown') );
alert( getPath('https://dev59.com/L3VD5IYBdhLWcg3wXamd/regex-url/?foo', 'unknown') );
alert( getPath('https://dev59.com/L3VD5IYBdhLWcg3wXamd/regex-url/#foo', 'unknown') );
alert( getPath('http://stackoverflow.com/', 'unknown') );


4

1
这很美。 - suchislife
正则表达式从URL中提取路径? - Max Barrass
他在询问关于正则表达式不存在的函数。 - Alin

4
你可以尝试这样做:
^(?:[^/]*(?:/(?:/[^/]*/?)?)?([^?]+)(?:\??.+)?)$

请注意,这不是全部URL的正则表达式。它只解决了在“//”之后第一个“/”和随后的“?”字符之间匹配所有文本的问题。其中([^?]+)是捕获组,返回您的路径。 如果您需要一个全匹配的正则表达式,您可以查看这个StackOverflow链接,他们讨论并分析了从其各个组成部分中提取URI的所有可能性,包括您的“路径”。
如果您认为这太复杂,而且如果您知道输入URL始终遵循在第一个“/”和随后的“?”之间具有您的路径的模式,则上述正则表达式就足够了。


2

我已经广泛地进行了工作,并且这是结果:

(?i)(?<scheme>http|https|ftp|sftp|sip|sips|file):\/\/(?:(?<username>[^`!@#$^&*()+=,:;'"{}\|\[\]\s\/\\]+)(?::(?<password>[^`!@#$^&*()+=,:;'"{}\|\[\]\s\/\\]+))?@)?(?:(?<ipv4>((?:(?:25[0-5]|2[0-4]\d|1?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|1?\d\d?)))|\[(?<ipv6>(?i)(?:[\da-f]{0,4}:){1,7}(?:(?<ipv4_in_ipv6>(?:(?:25[0-5]|2[0-4]\d|1?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|1?\d\d?))|[\da-f]{0,4}))\]|(?:(?<sub_domain>[^\s~`!@#$%^&*()_+=,.?:;'"{}\|\[\]\/\\]+\.)*(?<domain>[^\s~`!@#$%^&*()_+=,.?:;'"{}\|\[\]\/\\]+)(?<tld>\.[^\s~`!@#$%^&*()\-_+=,.?:;'"{}\|\[\]\/\\0-9]{2,})))+(?<port>:\d+)?(?:\/(?<path>\/?[^\s`@#$^&=.?"{}\\]+\/)*(?<file>[^\s`@#$^&=?"{}\/\\]+)?(?<query>\?[^\s`#$^"{}\\]+)*(?<fragment>#[^\s`$^&=?"{}\/\\]+)?)?

在您的情况下,只需要获取包含路径的组并添加您喜欢的单词,例如videoplay。更具体地说,我是指以下内容:

演示 | Git存储库

(?:\/videoplay(?<path>\/?[^\s`@#$^&=.?"{}\\]+\/)*(?<file>[^\s`@#$^&=?"{}\/\\]+)?(?<query>\?[^\s`#$^"{}\\]+)*(?<fragment>#[^\s`$^&=?"{}\/\\]+)?)?

2

虽然使用语言特性的答案很好,但这里还有一种使用正则表达式将URL拆分为组件的方法:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?
     ||            |  |          |       |   |        | |
     12 - scheme   |  |          |       |   |        | |
                   3  4 - authority, includes hostname/ip and port number.
                                 5 - path|   |        | |
                                         6   7 - query| |
                                                      8 9 - fragment

1

var subject =
'<link rel="shortcut icon" href="https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico?v=ec617d715196"><link rel="apple-touch-icon" href="https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png?v=c78bd457575a"><link rel="image_src" href="https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png?v=c78bd457575a">';
var re=/\"[a-z]+:\/\/[^ ]+"/m;
document.write(subject.match(re));

你可以尝试这个。
/\"[a-z]+:\/\/[^ ]+/

使用
if (/\"[a-z]+:\/\/[^ ]+/m.test(subject)) {  // Successful match } else {    // Match attempt failed }

1

您是指负向回顾后发现吗?(?<!/)


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