如何在文本中匹配URI?

如何在文本中匹配URI?,uri,textmatching,Uri,Textmatching,如何在文本块中发现URI 我们的想法是将这些文本转换成链接。如果只考虑http(s)和ftp(s)方案,这是非常简单的;然而,我猜想一般的问题(考虑到tel、mailto和其他URI方案)要复杂得多(如果可能的话) 如果可能的话,我更喜欢C#的解决方案。谢谢。对于许多协议,您可以只搜索“/”,不带引号。但是,不确定其他内容。某个内容是否是URI取决于上下文。一般来说,他们唯一的共同点是他们开始使用“scheme_name:”。方案名称可以是任何内容(取决于合法字符)。但其他字符串也包含冒号,而不

如何在文本块中发现URI

我们的想法是将这些文本转换成链接。如果只考虑http(s)和ftp(s)方案,这是非常简单的;然而,我猜想一般的问题(考虑到tel、mailto和其他URI方案)要复杂得多(如果可能的话)


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

对于许多协议,您可以只搜索“/”,不带引号。但是,不确定其他内容。

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

所以你需要决定你感兴趣的方案。通常,对于您关心的每个方案,您都可以搜索“scheme_name:”,后跟最多一个空格的字符。不幸的是,URI可能包含空格,因此如果它们嵌入到文本中,则可能会产生歧义。你无法解决歧义——写这篇文章的人必须修正它。URI可以选择包含在中。不过,大多数人不会这样做,所以认识到这种格式只会偶尔有所帮助

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


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

以下是一段代码片段,其中包含了各种需要的正则表达式:


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


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

下面的perl regexp应该执行此操作。c是否有perl regexp

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

正则表达式可能是一个很好的起点,尽管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)
  • 不存在antscheme://obvious.false.positive
  • http://www.google.com/search?q=uri+正则+表达式(匹配,但查询不匹配
    我认为这是80:20规则的一个例子。如果你想抓住大多数东西,那么我会按照建议去做,如果你不能自己编写一个正则表达式,那么我会找到一个合适的正则表达式
如果您看到的是从相当受控的来源(例如机器生成的)提取的文本,那么这将是最好的操作方法

如果您必须绝对准确地捕获您遇到的每个URI,并且您正在查看来自野外的文本,那么我想我会查找任何带有冒号的单词,例如
\s(\w:\s+)\s
。一旦您找到了一个合适的URI候选,然后将其传递给您正在使用的任何库的URI类中的真正的URI解析器

如果您对编写URI模式如此困难的原因感兴趣,那么我想可能是URI的定义是用a完成的,而正则表达式只能从中解析语言。

执行以下操作:

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

在维基百科上可以找到一个列表。我同意在网上搜索一个预制的正则表达式可能是最好的主意。你可以看看的源代码。
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;
},