RFC 2396的附录 B给出了解析 URI 的正则表达式。
B. 使用正则表达式解析 URI 引用
如第 4.3 节所述,通用 URI 语法不足以消除某些形式的 URI 的组件的歧义。由于该部分中描述的“贪婪算法”与 POSIX 正则表达式使用的消歧方法相同,因此使用正则表达式来解析 URI 引用的潜在四个组件和片段标识符是很自然且司空见惯的。
以下行是将 URI 引用分解为其组件的正则表达式。
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
12 3 4 5 6 7 8 9
上面第二行中的数字只是为了便于阅读;它们指示每个子表达式的参考点(即,每个成对的括号)。我们将与子表达式n匹配的值称为$<n>
。例如,将上面的表达式匹配到
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
where<undefined>
表示该组件不存在,如上例中查询组件的情况。因此,我们可以将四个组件和片段的值确定为
scheme = $2
authority = $4
path = $5
query = $7
fragment = $9
并且,在相反的方向上,我们可以使用第 5.2 节的步骤 7 中的算法从其组件重新创建 URI 引用。
正则表达式可直接在 Perl 中使用,如
if ($uri =~ m!^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?!) {
my($host,$path) = ($4,$5);
print "$host => $path\n";
}
正则表达式量词中的贪婪可能会使这种模式难以使用,s///
因为它会消耗尽可能多的文本,可能会超出未标记的 URI 边界。
更直接适用的是CPAN 上可用的URI::Find模块。限制 LEFT 和 RIGHT 就像
#! /usr/bin/env perl
use strict;
use warnings;
use URI::Find;
my $finder = URI::Find->new(sub {
my(undef,$found) = @_;
"LEFT $found RIGHT";
});
while (<>) {
$finder->find(\$_);
print;
}
输出:
$猫输入
这是一个纯文本输入,适用于
http://stackoverflow.com 上问题的答案
特别是,该问题可在
http://stackoverflow.com/q/15233535/123109 和答案
在 http://stackoverflow.com/a/15234378/123109
$ ./mark-uris 输入
这是一个纯文本输入,适用于
LEFT http://stackoverflow.com RIGHT 上问题的答案
特别是,该问题可在
左 http://stackoverflow.com/q/15233535/123109 右和答案
在左边 http://stackoverflow.com/a/15234378/123109 右边