如何在不使用Regex的情况下从Ruby中提取域名?

时间:2017-05-28 16:29:58

标签: ruby

如果表单中有一个电子邮件地址'foo@bar.com''rhubarb.foo@bar.com',那么如何只提取域bar(不是bar.com),而不诉诸正则表达式还是专业图书馆?

这篇文章:' How to get domain from email' 几乎回答了我的问题,但我不确定如何拆分域'bar.com',或者是否存在其他方法。

4 个答案:

答案 0 :(得分:1)

使用固定字符串方法对电子邮件地址进行分区

有许多基于字符串的方法,但最简单的方法之一(至少在我看来)是使用String#rpartition在地址中的终端@符号后抓取您需要的内容。例如,给定存储在电子邮件变量中的地址:

# Get domain-parts.
email.rpartition('@').last

# Get domain parts without the TLD.
email.rpartition('@').last.rpartition('.').first

这很简单,可靠,而且(最重要的是)相对容易阅读。

最右边的分区方法

要查看String#rpartition的实际效果,并了解子域或非典型本地部分的灵活性,请考虑以下结果:

emails = %w[
  foo@bar.com
  rhubarb.foo@bar.com
  foo@bar.baz.com
  foo+extension.address@subdomain.example.com
]

emails.map { |email| email.rpartition(?@).last.rpartition(?.).first }
#=> ["bar", "bar", "bar.baz", "subdomain.example"]

对分解的分配使用分区

使用String#partitionString#rpartition优于String#split的一个好处是,这两种方法可以自然地适合解构分配。例如:

email = "foo+extension.address@subdomain.example.com"

local_part, _, domain_part = email.rpartition ?@
#=> ["foo+extension.address", "@", "subdomain.example.com"]

hostname, _, top_level_domain = domain_part.rpartition ?.
#=> ["subdomain.example", ".", "com"]

因为解构允许您访问单独变量中的每个部分,所以此方法可用于为您的电子邮件地址创建各种替代表示,例如域的哈希和每个域中的本地部分。作为一个简单的例子,请考虑:

address_list = Hash.new { |k,v| k[v] = [] }

emails = %w[foo@example.com bar@example.com baz@other.example.com]

emails.each do |email|
  local_part, _, domain_part = email.rpartition ?@
  address_list[domain_part] << local_part
end

address_list
#=> {"example.com"=>["foo", "bar"], "other.example.com"=>["baz"]}

显然,您可以根据需要使结构变得简单或复杂。但是,像{"com"=>{"example"=>["foo"], "other.example"=>["bar"]}}这样复杂的结构是不实用的,并且可能存在更简单的解决方案的X / Y问题。然而,知道你可以通过去除和重组来做这些事情是有用的。

答案 1 :(得分:0)

您可以使用String#split实现此目的。

'foo@bar.com'.split('@')[1].split('.')[0] # => bar

...或者如果您需要支持子域名:

'foo@qux.bar.com'. split('@')[1]. reverse. split('.'). drop(1). map(&:reverse). reverse. join('.') # => qux.bar

答案 2 :(得分:0)

使用拆分功能:

mystring = "bar.com"
mystring.split('.') --> ["bar", "com"]

如果字符串包含子域,这甚至可以工作:

mystring = "night.bar.com"
mystring.split('.') --> ["night", "bar", "com"]

编辑:糟糕,两分钟太晚了:)

答案 3 :(得分:0)

以下是四个有效的电子邮件地址:

valid_email_addresses = ["a@b.com", "a@b.c.com", "\"a.@.b\"@c.com", "a@b"]

请参阅Wiki "Email address"

我们可以使用以下方法提取所需的字符串。

def domain_preface(str)
  # something here like: return nil unless email_address_valid?(str)
  s = str[str.rindex('@')+1..-1]
  i = s.rindex('.')
  return "" unless i
  s[0..s.rindex('.')-1]
end

valid_email_addresses.each { |s| puts "%s: |%s|" % [s, domain_preface(s)] }
a@b.com: |b|
a@b.c.com: |b.c|
"a.@.b"@c.com: |c|
a@b: ||