RFC3986
互联网工程任务组 ( IETF ) 的第 3986 号文档征求意见 (RFC) 标题为:“统一资源标识符 (URI):通用语法”( RFC3986 ),是描述构成有效的通用统一资源标识符 (URI)。附录 B介绍了您需要的正则表达式:
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
使用此正则表达式,URI 部分存储如下:
scheme = $2
authority = $4
path = $5
query = $7
fragment = $9
为了记录上面的正则表达式,我冒昧地用注释和缩进以自由间距模式重写它,并以经过测试的 PHP 脚本的形式呈现在这里,它解析出给定的所有主要部分URI 字符串:
PHP解决方案:
<?php // test.php Rev:20130830_0800
$re_rfc3986_parse_generic_uri = '%
# Parse generic URI according to RFC3986 Appendix B.
^ # Anchor to start of string.
(?: # Group for optional scheme.
([^:/?#]+) # $1: Uri SCHEME.
: # Scheme ends with ":".
)? # Scheme is optional.
(?: # Group for optional authority.
// # Authority starts with "//"
([^/?#]*) # $2: Uri AUTHORITY.
)? # Authority is optional.
([^?#]*) # $3: Uri PATH (required).
(?: # Group for optional query.
\? # Query starts with "?".
([^#]*) # $4: Uri QUERY.
)? # Query is optional.
(?: # Group for optional fragment.
\# # Fragment starts with "#".
(.*) # $5: Uri FRAGMENT.
)? # Fragment is optional.
$ # Anchor to end of string.
%x';
$text = "http://www.site.com/part1/part2?key=value#blub";
if (preg_match($re_rfc3986_parse_generic_uri, $text, $matches)) {
print_r($matches);
} else {
echo("String is not a valid URI");
}
?>
对原始正则表达式进行了两个功能更改:1.) 将不必要的捕获组转换为非捕获,以及 2.)$
在表达式末尾添加了字符串锚的结尾。请注意,可以通过使用命名捕获组而不是使用编号捕获组来创建更具可读性的版本,但不会直接转换为 JavaScript 语法。
PHP脚本输出:
Array
(
[0] => http://www.site.com/part1/part2?key=value#blub
[1] => http
[2] => www.site.com
[3] => /part1/part2
[4] => key=value
[5] => blub
)
JavaScript 解决方案:
这是一个经过测试的 JavaScript 函数,它将有效的 URI 分解为其各种组件:
// Parse a valid URI into its various parts per RFC3986.
function parseValidURI(text) {
var uri_parts;
var re_rfc3986_parse_generic_uri =
/^(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/;
// Use String.replace() with callback function to parse the URI.
text.replace(re_rfc3986_parse_generic_uri,
function(m0,m1,m2,m3,m4,m5) {
uri_parts = {
scheme : m1,
authority : m2,
path : m3,
query : m4,
fragment : m5
};
return; // return value is not used.
});
return uri_parts;
}
undefined
请注意,如果 URI 字符串中不存在,则返回对象的非路径属性可能存在。此外,如果 URI 字符串与此正则表达式不匹配(即明显无效),则返回值为undefined
.
笔记:
- 唯一需要的通用 URI 组件是路径(它本身可能是空的)。
- 空字符串是有效的 URI!
- 上面的正则表达式不验证 URI,而是解析给定的有效 URI。
- 如果上述正则表达式无法匹配 URI 字符串,则该字符串不是有效的 URI。然而,反之则不成立——如果字符串确实匹配上面的正则表达式,这并不意味着 URI 是有效的,而只是意味着它可以作为一个 URI 进行解析。
对于那些对验证URI 并进一步分解感兴趣的人,我写了一篇文章,其中包含 RFC3986 附录 A 中定义的所有部分并将它们转换为正则表达式语法。看:
快乐的正则表达式!