RFC3986
互联网工程任务组(IETF)的请求评论(RFC)文档编号3986,标题为:“统一资源标识符(URI):通用语法”(RFC3986),是描述构成有效通用统一资源标识符(URI)所有组件精确语法的权威标准。 附录B 提供了您需要的正则表达式:
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
使用这个正则表达式,URI的各个部分被存储如下:
方案 = $2
权限 = $4
路径 = $5
查询 = $7
片段 = $9
为了记录上述正则表达式,我已经在自由空间模式下进行了重写,并添加了注释和缩进。下面以一个经过测试的PHP脚本的形式呈现,该脚本解析给定URI字符串的所有主要部分:
<?php
$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分解为其各个组件:
function parseValidURI(text) {
var uri_parts;
var re_rfc3986_parse_generic_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 uri_parts;
}
请注意,如果URI字符串中不存在返回对象的非路径属性,则这些属性可能为
undefined
。此外,如果URI字符串不匹配此正则表达式(即明显无效),则返回值为
undefined
。
注意事项:
- 通用URI的唯一组件是路径(本身可以为空)。
- 空字符串是有效的URI!
- 上述正则表达式不验证URI,而是解析给定的有效URI。
- 如果上述正则表达式无法匹配URI字符串,则该字符串不是有效的URI。但反之不成立——如果字符串与上述正则表达式匹配,则并不意味着URI有效,而只是表示它可解析为URI。
- 对于那些有兴趣验证URI并进一步分解它的人,我写了一篇文章,其中将RFC3986附录A中定义的所有部分转换为正则表达式语法。请参见:
正则表达式URI验证
祝你使用正则表达式愉快!