3

如何在文本块中发现 URI?

这个想法是将这样的文本运行变成链接。如果只考虑 http(s) 和 ftp(s) 方案,这很简单;但是,我猜一般问题(考虑到 tel、mailto 和其他 URI 方案)要复杂得多(如果可能的话)。

如果可能的话,我更喜欢 C# 中的解决方案。谢谢你。

4

7 回答 7

7

正则表达式可能证明是一个很好的起点,尽管众所周知,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 语法的语言。

于 2008-09-17T13:45:39.997 回答
1

某个东西是否是 URI 取决于上下文。一般来说,它们唯一的共同点是它们以“scheme_name:”开头。方案名称可以是任何名称(受合法字符限制)。但其他字符串也包含冒号,而不是 URI。

因此,您需要确定您感兴趣的方案。通常,您可以搜索“scheme_name:”,然后为您关心的每个方案搜索直到空格的字符。不幸的是,URI 可以包含空格,因此如果它们嵌入到文本中,它们可能会产生歧义。您无法解决歧义 - 编写文本的人必须解决它。URI 可以选择包含在 <> 中。但是,大多数人不会这样做,因此认识到这种格式只会偶尔有所帮助。

URI 的 Wikipedia 文章列出了相关的 RFC。

[编辑添加:使用正则表达式来完全验证 URI 是一场噩梦——即使你以某种方式找到或创建了一个正确的,它也会非常大并且难以评论和维护。幸运的是,如果您所做的只是突出显示链接,您可能并不关心奇怪的误报,因此您不需要验证。只需查找“http://”、“mailto:\S*@”等]

于 2008-09-17T12:18:20.690 回答
0

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;
},
于 2008-09-17T21:35:29.040 回答
0

对于很多协议,您可以只搜索“://”而不带引号。虽然不确定其他人。

于 2008-09-17T12:13:22.450 回答
0

这是一个带有正则表达式的代码片段,可满足各种需求:

http://snipplr.com/view/6889/regular-expressions-for-uri-validationparsing/

于 2008-09-17T12:21:20.277 回答
0

这并不容易做到,如果你还想匹配“something.tld”,因为普通文本会有很多该模式的实例,但如果你只想匹配以方案开头的 URI,你可以试试这个正则表达式(对不起,我不知道如何将它插入C#)

(http|https|ftp|mailto|tel):\S+[/a-zA-Z0-9]

您可以在那里添加更多方案,它会匹配方案直到下一个空白字符,考虑到最后一个字符不是无效的(例如在非常常见的字符串“ http://www.example.com ”中。 )

于 2008-09-17T12:26:10.017 回答
-1

下面的 perl 正则表达式应该可以解决问题。c# 有 perl 正则表达式吗?

/\w+:\/\/[\w][\w\.\/]*/
于 2008-09-17T12:33:33.913 回答