如何在文本块中发现 URI?
这个想法是将这样的文本运行变成链接。如果只考虑 http(s) 和 ftp(s) 方案,这很简单;但是,我猜一般问题(考虑到 tel、mailto 和其他 URI 方案)要复杂得多(如果可能的话)。
如果可能的话,我更喜欢 C# 中的解决方案。谢谢你。
如何在文本块中发现 URI?
这个想法是将这样的文本运行变成链接。如果只考虑 http(s) 和 ftp(s) 方案,这很简单;但是,我猜一般问题(考虑到 tel、mailto 和其他 URI 方案)要复杂得多(如果可能的话)。
如果可能的话,我更喜欢 C# 中的解决方案。谢谢你。
正则表达式可能证明是一个很好的起点,尽管众所周知,URI 和 URL 很难与单个模式匹配。
为了说明,最简单的模式看起来相当复杂(在 Perl 5 表示法中):
\w+:\/{2}[\d\w-]+(\.[\d\w-]+)*(?:(?:\/[^\s/]*))*
这将匹配
http://example.com/foo/bar-baz
和
ftp://192.168.0.1/foo/file.txt
但至少会导致以下问题:
mailto:support@stackoverflow.com
(不匹配 - 不//
,但存在@
)ftp://192.168.0.1.2
(匹配,但数字太多,所以它不是有效的 URI)ftp://1000.120.0.1
(匹配,但 IP 地址需要 0 到 255 之间的数字,因此它不是有效的 URI)nonexistantscheme://obvious.false.positive
http://www.google.com/search?q=uri+regular+expression
(匹配,但查询不是我认为这是 80:20 规则的情况。如果你想捕捉大多数东西,那么如果你自己不能写一个,我会按照建议找到一个像样的正则表达式。如果您正在查看从相当受控的来源(例如机器生成)中提取的文本,那么这将是最好的行动方案。
如果您绝对必须捕获遇到的每个 URI,并且您正在查看来自野外的文本,那么我想我会查找其中带有冒号的任何单词,例如\s(\w:\S+)\s
. 一旦你有一个合适的 URI 候选者,然后将它传递给你正在使用的任何库的 URI 类中的真实 URI 解析器。
如果您对编写 URI 模式如此困难的原因感兴趣,我想可能是 URI 的定义是使用Type-2 语法完成的,而正则表达式只能解析来自Type-3 语法的语言。
某个东西是否是 URI 取决于上下文。一般来说,它们唯一的共同点是它们以“scheme_name:”开头。方案名称可以是任何名称(受合法字符限制)。但其他字符串也包含冒号,而不是 URI。
因此,您需要确定您感兴趣的方案。通常,您可以搜索“scheme_name:”,然后为您关心的每个方案搜索直到空格的字符。不幸的是,URI 可以包含空格,因此如果它们嵌入到文本中,它们可能会产生歧义。您无法解决歧义 - 编写文本的人必须解决它。URI 可以选择包含在 <> 中。但是,大多数人不会这样做,因此认识到这种格式只会偶尔有所帮助。
URI 的 Wikipedia 文章列出了相关的 RFC。
[编辑添加:使用正则表达式来完全验证 URI 是一场噩梦——即使你以某种方式找到或创建了一个正确的,它也会非常大并且难以评论和维护。幸运的是,如果您所做的只是突出显示链接,您可能并不关心奇怪的误报,因此您不需要验证。只需查找“http://”、“mailto:\S*@”等]
Ubiquity的URL 工具执行以下操作:
findURLs: function(text) {
var urls = [];
var matches = text.match(/(\S+\.{1}[^\s\,\.\!]+)/g);
if (matches) {
for each (var match in matches) {
urls.push(match);
}
}
return urls;
},
对于很多协议,您可以只搜索“://”而不带引号。虽然不确定其他人。
这是一个带有正则表达式的代码片段,可满足各种需求:
http://snipplr.com/view/6889/regular-expressions-for-uri-validationparsing/
这并不容易做到,如果你还想匹配“something.tld”,因为普通文本会有很多该模式的实例,但如果你只想匹配以方案开头的 URI,你可以试试这个正则表达式(对不起,我不知道如何将它插入C#)
(http|https|ftp|mailto|tel):\S+[/a-zA-Z0-9]
您可以在那里添加更多方案,它会匹配方案直到下一个空白字符,考虑到最后一个字符不是无效的(例如在非常常见的字符串“ http://www.example.com ”中。 )
下面的 perl 正则表达式应该可以解决问题。c# 有 perl 正则表达式吗?
/\w+:\/\/[\w][\w\.\/]*/