如何匹配网址但从匹配项中排除终结符?

时间:2011-03-27 18:07:32

标签: ruby regex

我希望在文本中匹配网址并将其替换为锚标记,但我想排除一些终结符,就像Twitter在推文中匹配网址一样。

到目前为止,我已经得到了这个,但显然效果不佳。

(http[s]?\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?)

编辑:一些示例网址。在下面的所有情况下,我只想匹配“http://www.example.com”

http://www.example.com

http://www.example.com

“http://www.example.com”

http://www.example.com;

http://www.example.com

[http://www.example.com]

{http://www.example.com}

http://www.example.com *

4 个答案:

答案 0 :(得分:2)

去年我研究了这个问题并开发了一个您可能想要查看的解决方案 - 请参阅:URL Linkification (HTTP/FTP)此链接是Javascript解决方案的测试页面,其中包含许多难以链接的URL示例

我的正则表达式解决方案,为PHP和Javascript编写 - (但很容易被翻译成Ruby)并不简单(但事实证明也不是问题。)有关更多信息,我建议也阅读:

Jeff Atwood的

The Problem With URLs和 约翰格鲁伯An Improved Liberal, Accurate Regex Pattern for Matching URLs

如果您想要正确执行此操作,必须阅读Jeff的博客文章后面的评论......

答案 1 :(得分:2)

Ruby的URI模块有一个extract方法,用于从文本中解析出URL。通过解析返回的值,您可以依靠模块中的启发式方法从URL中提取方案和主机信息,从而避免重新发明轮子。

text = '
http://www.example.com.
http://www.example.com:
"http://www.example.com"
http://www.example.com;
http://www.example.com!
[http://www.example.com]
{http://www.example.com}
http://www.example.com*
http://www.example.com/foo/bar?q=foobar
http://www.example.com:81
'

require 'uri'

puts URI::extract(text).map{ |u| uri = URI.parse(u); "#{ uri.scheme }://#{ uri.host[/(^.+?)\.?$/, 1] }" }

# >> http://www.example.com
# >> http://www.example.com
# >> http://www.example.com
# >> http://www.example.com
# >> http://www.example.com
# >> http://www.example.com
# >> http://www.example.com
# >> http://www.example.com
# >> http://www.example.com
# >> http://www.example.com

唯一的问题是句点'.'是主机名中的合法字符,因此URI #host不会删除它。那些被捕获在重建URL的map语句中。请注意,URI正在剥离路径和查询信息。

答案 2 :(得分:1)

一个实用且易于理解的解决方案是:

regex = %r!"(https?://[-.\w]+\.\w{2,6})"!

一些注意事项:

  • 使用%r,我们可以选择开始和结束分隔符。在这种情况下,我使用了感叹号,因为我想在正则表达式中使用斜杠。
  • 可选的量词(即'?')仅与前面的表达式绑定,在本例中为's'。没有必要将's'放在字符类[s]?中。它与s?相同。
  • 在角色类[-.\w]内,我们不需要逃避破折号和点,以使它们在字面上匹配点和破折号。但是,短跑应该是第一个,而不是指范围。
  • \w匹配Ruby中的[A-Za-z0-9_]。它并不完全是URL字符的完整定义,但结合使用破折号和点符号可能足以满足我们的需求。
  • 热门域名长度在2到6个字符之间,例如'.se'和'.travel'
  • 我不确定你的意思我想排除一些终结者但这个正则表达式只匹配你的例子中想要的那个。
  • 我们想要使用第一个捕获组,例如像这样:

    如果输入=〜%r!“(https?:// [ - 。\ w] +。\ w {2,6})”!

    匹配= $〜[1]

    否则

    match =“”

答案 3 :(得分:0)

这个怎么样?

%r|https?://[-\w.]*\w|