需要正则表达式才能获取所有内容,包括扩展名+拒绝重复项

时间:2016-03-05 22:56:32

标签: ruby regex

我有这个字符串:

http://www.amazon.com/books-used-books-textbooks/b%3Fie%3DUTF8%26node%3D283155
http://www.amazon.com/gp/site-directory
http://www.amazon.com/gp/goldbox
https://en.wikipedia.org/wiki/A
http://webcache.googleusercontent.com/search%3Fhl%3Den%26biw%26bih%26q%3Dcache:GLRqJLrDZEQJ:https://en.wikipedia.org/wiki/A%252Ba%26gbv%3D1%26%26ct%3Dclnk
https://twitter.com/a%3Flang%3Den
http://webcache.googleusercontent.com/search%3Fhl%3Den%26biw%26bih%26q%3Dcache:4teZIJ7lbgsJ:https://twitter.com/a%3Flang%253Den%252Ba%26gbv%3D1%26%26ct%3Dclnk
http://dictionary.reference.com/browse/a
http://webcache.googleusercontent.com/search%3Fhl%3Den%26biw%26bih%26q%3Dcache:Pn8j0e0faiAJ:http://dictionary.reference.com/browse/a%252Ba%26gbv%3D1%26%26ct%3Dclnk
http://boards.4chan.org/a/

我需要抓住所有信息到" .com"," .org"或" .net"结束。

预期输出应如下所示:

http://www.amazon.com/
https://en.wikipedia.org/
http://dictionary.reference.com/
http://webcache.googleusercontent.com/
http://boards.4chan.org/

到目前为止,我尝试了一些事情:

  • /(\/)([^\/]+)\Z/
  • ^(http[s]?)(...)\w{3}\
  • /https?:\/\/[\S]/

他们都没有工作,所以现在我来了。如果有更简单的方法,请告诉我。如果有的话,我还需要拒绝重复。

5 个答案:

答案 0 :(得分:1)

使用URI模块(s是您的字符串):

require 'uri'

s.split(/\n/).map { |line|
    uri = URI(line)
    uri.scheme + "://" + uri.host
}.uniq

注意:如果您的字符串来自文件,则不需要使用split:

File.open('yourfile').map { |line|
    uri = URI(line)
    uri.scheme + "://" + uri.host
}.uniq

答案 1 :(得分:1)

不要重新发明轮子,重复使用现有轮子:

require 'uri'

%w[
  http://www.amazon.com/books-used-books-textbooks/b%3Fie%3DUTF8%26node%3D283155
  http://www.amazon.com/gp/site-directory
  http://www.amazon.com/gp/goldbox
  https://en.wikipedia.org/wiki/A
  http://webcache.googleusercontent.com/search%3Fhl%3Den%26biw%26bih%26q%3Dcache:GLRqJLrDZEQJ:https://en.wikipedia.org/wiki/A%252Ba%26gbv%3D1%26%26ct%3Dclnk
  https://twitter.com/a%3Flang%3Den
  http://webcache.googleusercontent.com/search%3Fhl%3Den%26biw%26bih%26q%3Dcache:4teZIJ7lbgsJ:https://twitter.com/a%3Flang%253Den%252Ba%26gbv%3D1%26%26ct%3Dclnk
  http://dictionary.reference.com/browse/a
  http://webcache.googleusercontent.com/search%3Fhl%3Den%26biw%26bih%26q%3Dcache:Pn8j0e0faiAJ:http://dictionary.reference.com/browse/a%252Ba%26gbv%3D1%26%26ct%3Dclnk
  http://boards.4chan.org/a/
].map{ |s|
  scheme, _, host = URI.split(s)
  "#{ scheme }://#{ host }"
}.uniq
# => ["http://www.amazon.com", "https://en.wikipedia.org", "http://webcache.googleusercontent.com", "https://twitter.com", "http://dictionary.reference.com", "http://boards.4chan.org"]

如果您的数据是字符串,则将其拆分为行并迭代它们:

str = "foo
bar
baz"

str.lines.map(&:rstrip)
# => ["foo", "bar", "baz"]

答案 2 :(得分:0)

/^(http[s]?:\/\/[^\/]*)\//会做到这一点

答案 3 :(得分:0)

我用来捕获URL的不同部分的正则表达式是:

^(?<uri_schema_and_host>(?<uri_scheme>https|http):\/\/(?<uri_host>[^\/]+))(?<uri_path>\/[^?]*?)?(?<uri_query>\?.*)?$

这会为URL的许多部分创建命名捕获。我们可以根据您的需要缩短这一点:

^((https|http):\/\/[^\/]+).*$

在Ruby中,您可以使用scan method on String轻松利用此功能,然后使用uniq对结果进行重复数据删除:

regex = /^(?<uri_schema_and_host>(?<uri_scheme>https|http):\/\/(?<uri_host>[^\/]+))(?<uri_path>\/[^?]*?)?(?<uri_query>\?.*)?$/m

results = text.scan regex

scheme_and_hosts = results.map {|x| x[0].to_s }
scheme_and_hosts.uniq!

scheme_and_hosts.each {|x| puts x }

ruby​​脚本中正则表达式末尾的/.../m分别匹配每一行,因此scan会在每一行找到匹配项。

答案 4 :(得分:0)

你需要避免重复的事实使它有点复杂:

/(?:^|\n)(https?:\/\/[^\/]*?\.(?:com|org|net)\/?)(?!(?:.|\n)*\n\1)/

首先,(?:^|\n)检查它是否是新行的开头,因为我们不想匹配行中间的任何内容。然后我们开始使用(捕获我们的论坛。我们匹配https(如果存在),后跟冒号和两个转义斜杠:\/\/。然后我们捕获除了斜线之外的所有东西,具有懒惰的行为 - 尽可能少地捕获。在这里我们可以捕捉到任何角色,但斜线是一个很好的迹象,表明我们走得太远,所以我们不希望这样。然后我们捕获一个转义点\.,然后是一个非捕获组,它允许我们使用com,org或net:(?:com|org|net)。最后,如果有一个尾随反斜杠,\/?也会捕获它,并且捕获组会以)结束。

这是有趣的地方。虽然我们已成功捕获了链接,但我们希望避免重复。为此,我们采用负面预测。我们声称我们不想找到:

  • 任意字符,甚至是新的换行符(?:.|\n),尽可能多地使用,然后是:
  • 新行\n,后跟
  • 我们刚捕获的整个捕获组。

最后一点非常重要 - 这是我们确保不会得到任何重复的方式。如果我们匹配,例如amazon.comamazon.com存在于任何前方,不会被捕获。因此,只会捕获amazon.com的最后一个实例。

图形可视化可能有助于更好地理解它: A graphical visualization of the regex string