如何匹配文本中的URI?

时间:2008-09-17 12:10:33

标签: uri textmatching

如何在一个文本块中发现URI?

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

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

7 个答案:

答案 0 :(得分:6)

正则表达式可能是一个很好的起点,尽管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 grammar来完成的,而正则表达式只能解析来自{的语言。 {3}}

答案 1 :(得分:1)

某个URI是否与上下文相关。一般来说,他们唯一的共同点就是他们开始“scheme_name:”。方案名称可以是任何内容(受法律字符限制)。但是其他字符串也包含冒号而不是URI。

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

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

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

答案 2 :(得分:0)

对于很多协议,你可以只搜索“://”而不用引号。但不确定其他人。

答案 3 :(得分:0)

以下是包含各种需求的正则表达式的代码段:

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

答案 4 :(得分:0)

如果您还要匹配“something.tld”,这并不容易,因为普通文本将包含该模式的许多实例,但如果您只想匹配以方案开头的URI,则可以尝试这个正则表达式(抱歉,我不知道如何用C#插入它)

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

您可以在那里添加更多方案,并且它将匹配方案直到下一个空格字符,同时考虑到最后一个字符无效(例如,在通常的字符串“http://www.example.com”中。)

答案 5 :(得分:0)

URL Tool for Ubiquity执行以下操作:

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

答案 6 :(得分:-1)

下面的perl regexp应该可以解决问题。 c#有perl regexps吗?

/\w+:\/\/[\w][\w\.\/]*/