获取 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. (加上其他你认为有用的东西)

即使我输入以下网址,正则表达式也应正确运作:

http://example.example.com/example/example/example.html
308832 次浏览

一个正则表达式分析和分解 包含查询参数的完整 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 [’$&’] ,

协议: 正则表达式,

主办机构: 正版表格,

路径: 正则表达式,

文件: 正则表达式 $6,

Query: RegExp. $7,

散列: 正则表达式。 $8

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

会这样做:

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

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

试试以下方法:

^((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://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://www.fileformat.info/tool/regex.htm家庭烤面包机的正则表达式工作得很好。

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

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

Hometoast 的建议很棒,但是在我的例子中,我认为它没有帮助(除非我在所有枚举中复制粘贴相同的正则表达式)。

这就是为什么我希望给出每种情况的正则表达式的答案

我知道您声称这是语言无关的,但是您能告诉我们您使用的是什么吗? 这样我们就可以知道您具有什么样的正则表达式功能了?

如果你有非捕获匹配的能力,你可以修改家庭吐司的表达式,让你不感兴趣捕获的子表达式像这样设置:

(?:SOMESTUFF)

您仍然需要将正则表达式复制粘贴(并稍作修改)到多个位置,但这是有意义的——您不仅要检查子表达式是否存在,还要检查它是否存在 作为 URL 的一部分。对子表达式使用非捕获修饰符可以得到您需要的东西,仅此而已,如果我没有理解错的话,这正是您想要的。

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

https?

将匹配“ http”或“ https”就可以了。

Java 提供了一个 URL 类来实现这一点

另外,PHP 提供 Parse _ url ()

我发现投票最多的答案(家庭吐司的答案)对我来说并不完美。有两个问题:

  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];
}
/^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/

从我的 类似的问题的答案。由于存在一些 bug (例如不支持用户名/密码,不支持单字符文件名,片段标识符被破坏) ,所以比上面提到的其他一些文件工作得更好。

Regexp 获取没有该文件的 URL 路径。

Url = ‘ http://domain/dir1/dir2/somefile’ Url.scanner (/^ (http://[ ^/] +)((? :/[ ^/] +) + (? =/)) ?/? (? : [ ^/] +) ? $/i) . to _ s

它对于向这个 url 添加相对路径非常有用。

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

没有这样做的标准,也不能简单地使用字符串解析或正则表达式来产生正确的结果。首先,我使用正则表达式的功能,但不是所有的网址可以解析子域正确。实践方法是使用 TLD 列表。在定义了 URL 的 TLD 之后,左边的部分是域,剩下的部分是子域。

然而,列表需要维护它,因为新的顶级域名是可能的。目前我知道的 publicsuffix.org 是维护最新的列表,你可以使用 google code 中的 DomainName-parser 工具来解析公共后缀列表,并通过使用 DomainName object: domainName 轻松获得子域名、域名和 TLD。子域名,域名。域名和域名。

这个答案也很有帮助: 从 URL 获取子域

呼叫

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

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

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

   // 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'
}

我需要一个正则表达式来匹配所有的 url 地址,然后做了这个:

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

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

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]

我知道我迟到了,但是有一个简单的方法可以让浏览器在不使用正则表达式的情况下为你解析一个 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
*/

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

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

以上这些方法对我都不管用。以下是我最后使用的方法:

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

提出一个更具可读性的解决方案(在 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'
}

我试图用 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]+))?))?)?)?((?:\/?(?:[^\/\?#]+\/+)*)(?:[^\?#]*)))?(\?[^#]+)?)(#.*)?

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

各部分按顺序排列:

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 (亦可在 bower 下载)

如果你有一个改进,请创建一个拉请求与更多的测试,我会接受并感谢合并。

我迟到了几年,但令我惊讶的是,没有人提到统一资源标志符规范有一个 关于使用正则表达式解析 URI 的部分。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 中的正斜杠:

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

我喜欢发表在“ Javascript: The Good Part”中的 regex。 它不太短也不太复杂。 Github 上的这个页面也有使用它的 JavaScript 代码。 但它可以适用于任何语言。 Https://gist.github.com/voodoogq/4057330

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://
Www.thomas-bayer.com
3:/
4: axis2/services/BLZService? wsdl

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

好好享受。
Yosi Lev

执行完整解析的正则表达式非常糟糕。为了便于阅读,我已经包含了命名的反向引用,并将每个部分划分为不同的行,但它看起来仍然是这样的:

^(?:(?P\w+(?=:\/\/))(?::\/\/))?
(?:(?P(?:(?:&(?: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[0-9]+))?)\/)?
(?:(?P(?:(?:&(?: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(?:(?:&(?: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(?:(?:&(?: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.*))?$

要求它如此详细的事情是,除了协议或端口之外,任何部分都可以包含 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(?:ht|f)tps?|\w+(?=:\/\/))(?::\/\/))?
(?:(?P(?:\{\{htmlentity}}|[^\/?#:])+(?::(?P[0-9]+))?)\/)?
(?:(?P(?:\{\{htmlentity}}|[^?#])+)\/)?
(?P(?:\{\{htmlentity}}|[^?#])+)
(?:\?(?P(?:\{\{htmlentity}};|[^#])+))?
(?:#(?P.*))?$

当然,在 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