寻找一种方法来匹配以特定 tld 结尾的任何域电子邮件

Looking for a way to match any domain email ending with certain tld

正则表达式的新手,ruby 正在寻找一种方法来匹配任何以特定 tld 结尾的域

我有以下电子邮件:

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

我正在尝试编写一个正则表达式来匹配任何具有顶级域 .mil 和 .gov 的电子邮件,但不匹配其他域。我试过以下方法:

/(..).mil/

但我不知道如何让它匹配之前的所有内容.mil

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

我认为你是这个意思,

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

在ruby,

string.scan(/^.*(?=\.(?:gov|mil)$)/)

DEMO

我会使用类似的东西:

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 将模式应用于字符串,returns 匹配或 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
# >> 

以更 "production-worthy" 的方式使用它:

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? returns a true/false whether the string ends with that substring, which is faster than using the equivalent regular expression. any? 遍历数组寻找任何匹配条件和 returns true/false.

如果您要检查一长串 TLD,使用编写良好的正则表达式会非常快,可能比使用 any? 更快。这完全取决于您的数据和要检查的 TLD 的数量,因此您需要 运行 对数据抽样进行基准测试以查看要走的路。