正在寻找一种方法来匹配以某些tld

时间:2015-09-24 17:42:18

标签: ruby regex rubular

regex和ruby的新手正在寻找一种方法来匹配任何以特定tld结尾的域名

我有以下电子邮件:

jane.doe@navy.mil
barak.obama@whitehouse.gov
john.doe@usa.army.mil
family@example.com

我正在尝试编写一个正则表达式,它将匹配任何具有顶级域.mil和.gov的电子邮件,但不会编写其余的。我尝试了以下内容:

/(..).mil/

但我不知道如何让它在.mil

之前匹配所有内容

我正在使用红宝石。这是我在rubular中尝试的内容: http://rubular.com/r/BP7tqgAntY

2 个答案:

答案 0 :(得分:3)

认为你的意思是,

ADStructure
  |
  +-- ServiceData
        |
        +-- Eddystone
              |
              +-- EddystoneUID
              +-- EddystoneURL
              +-- EddystoneTLM

在红宝石中,

^(.*)\.(?:gov|mil)$

DEMO

答案 1 :(得分:1)

我会使用类似的东西:

REGEX = /\.(?:mil|gov)$/

%w[
  jane.doe@navy.mil
  barak.obama@whitehouse.gov
  john.doe@usa.army.mil
  family@example.com
].each do |addr|
  puts '"%s" %s' % [addr, (addr[REGEX] ? 'matches' : "doesn't match")]
end
# >> "jane.doe@navy.mil" matches
# >> "barak.obama@whitehouse.gov" matches
# >> "john.doe@usa.army.mil" matches
# >> "family@example.com" doesn't match

如果你知道你想要的TLD总是在字符串的末尾,那么一个匹配的简单模式就可以了。

这是有效的,因为addr[REGEX]使用String's [] method将模式应用于字符串并返回匹配或nil:

'foo'[/oo/] # => "oo"
'bar'[/oo/] # => nil

如果您想在TLD之前捕获所有内容:

REGEX = /(.+)\.(?:mil|gov)$/

%w[
  jane.doe@navy.mil
  barak.obama@whitehouse.gov
  john.doe@usa.army.mil
  family@example.com
].map do |addr|
  puts addr[REGEX, 1]
end
# >> jane.doe@navy
# >> barak.obama@whitehouse
# >> john.doe@usa.army
# >> 

以更具“生产价值”的风格使用它:

SELECT_PATTERN = '\.(?:mil|gov)$' # => "\\.(?:mil|gov)$"
CAPTURE_PATTERN = "(.+)#{ SELECT_PATTERN }" # => "(.+)\\.(?:mil|gov)$"

SELECT_REGEX, CAPTURE_REGEX = [SELECT_PATTERN, CAPTURE_PATTERN].map{ |s|
  Regexp.new(s)
}

SELECT_REGEX # => /\.(?:mil|gov)$/
CAPTURE_REGEX # => /(.+)\.(?:mil|gov)$/

addrs = %w[
  jane.doe@navy.mil
  barak.obama@whitehouse.gov
  john.doe@usa.army.mil
  family@example.com
].select{ |addr|
  addr[SELECT_REGEX]
}.map { |addr|
  addr[CAPTURE_REGEX, 1]
}

puts addrs

# >> jane.doe@navy
# >> barak.obama@whitehouse
# >> john.doe@usa.army

同样,你可以在没有正则表达式的情况下完成:

TLDs = %w[.mil .gov]

%w[
  jane.doe@navy.mil
  barak.obama@whitehouse.gov
  john.doe@usa.army.mil
  family@example.com
].each do |addr|
  puts '"%s" %s' % [ addr, TLDs.any?{ |tld| addr.end_with?(tld) } ]
end

# >> "jane.doe@navy.mil" true
# >> "barak.obama@whitehouse.gov" true
# >> "john.doe@usa.army.mil" true
# >> "family@example.com" false

TLDs = %w[.mil .gov]

addrs = %w[
  jane.doe@navy.mil
  barak.obama@whitehouse.gov
  john.doe@usa.army.mil
  family@example.com
].select{ |addr|
  TLDs.any?{ |tld| addr.end_with?(tld) }
}.map { |addr|
  addr.split('.')[0..-2].join('.')
}

puts addrs

# >> jane.doe@navy
# >> barak.obama@whitehouse
# >> john.doe@usa.army

end_with?返回true / false,无论字符串是否以该子字符串结尾,这比使用等效的正则表达式更快。 any?查看数组以查找任何匹配条件并返回true / false。

如果要查看很长的TLD列表,使用编写良好的正则表达式可能会非常快,可能比使用any?更快。这一切都取决于您的数据和要检查的TLD数量,因此您需要根据数据样本运行基准测试,以了解要走哪条路。