如何在文本中匹配URI?

3

如何在文本块中识别URI?

这个想法是将这些文本转化为链接。如果只考虑http(s)和ftp(s)协议,这很容易实现; 但是,我猜想一般问题(考虑tel,mailto和其他URI协议)会更加复杂(如果可能的话)。

如果可能的话,我希望使用C#解决方案。谢谢。


在维基百科上可以找到官方IANA注册URI方案的列表。我同意在网上搜索预制正则表达式可能是最好的想法。 - Aleksi Yrttiaho
你可以看一下Regexp::Common::URI的源代码。 - rami
7个回答

7
正则表达式可能是一个很好的起点,尽管URI和URL非常难以用单个模式匹配。
举个例子,最简单的模式看起来相当复杂(使用Perl 5符号表示):

\w+:\/{2}[\d\w-]+(\.[\d\w-]+)*(?:(?:\/[^\s/]*))*

这将匹配http://example.com/foo/bar-bazftp://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 grammar完成的,而正则表达式只能解析Type-3 grammars语言。

1

某物是否为URI取决于上下文。一般来说,它们唯一的共同点是以"scheme_name:"开头。方案名称可以是任何内容(符合法律字符)。但其他字符串也包含有冒号而不是URI。

所以你需要决定你感兴趣的方案。通常情况下,你可以搜索每个你关心的方案中跟随空格的字符,然后在其后添加"scheme_name:"。不幸的是,URI可能包含空格,因此如果它们嵌入到文本中,则有潜在的歧义。你无法解决这种歧义-撰写文本的人必须修复它。URI可以选择用<>括起来。大多数人不会这样做,因此识别这种格式只会偶尔有所帮助。

维基百科上的URI文章列出了相关的RFC。

[编辑添加:使用正则表达式完全验证URI非常困难-即使你找到或创建一个正确的,它也会非常庞大,难以评论和维护。幸运的是,如果你只是突出显示链接,你可能不需要验证偶尔的误报,因此你不需要验证。只需搜索"http://"、"mailto:\S*@"等即可]


0

如果你想匹配"something.tld",那就不太容易了,因为普通文本中会有很多这种模式的实例。但是,如果你只想匹配以一个scheme开头的URI,你可以尝试使用这个正则表达式(抱歉,我不知道如何在C#中使用它)

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

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


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;
},

0

对于许多协议,您可以只搜索“://”(不带引号)。不过其他的我就不确定了。


0

-1
以下的Perl正则表达式应该可以胜任。C#有Perl正则表达式吗?
/\w+:\/\/[\w][\w\.\/]*/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接