如何使这个正则表达式规则不区分大小写

6

我正在进行以下操作:

email = 'bob@luv.southwest.com'

domain_rules = [/craigslist.org/, /evite.com/, /ziprealty.com/, /alleyinsider.com/, /fedexkinkos.com/, /luv.southwest.com/, /fastsigns.com/, /experts-exchange.com/, /feedburner.com/]

user, domain = email.split('@')

domain_rules.each { |rule| return true if !domain.match(rule).nil? }

问题是这个区分大小写。有没有一种方法可以使它不区分大小写,而不必在每个规则的末尾添加/i?

6个回答

11

使用选项"i"(忽略大小写)

domain_rules = [
  /craigslist.org/i,
  /evite.com/i,
  /ziprealty.com/i,
  /alleyinsider.com/i,
  /fedexkinkos.com/i,
  /luv.southwest.com/i,
  /fastsigns.com/i,
  /experts-exchange.com/i,
  /feedburner.com/i
]

在这里测试... http://rubular.com/


谢谢,但这正是我想要避免的。 - AnApprentice
你为什么想要避免这个? - Ollie
为什么不使用一个规则适用于所有情况呢? /\bcraigslist.org\b|\bbevite.com\b|\bziprealty.com\b/i http://rubular.com/r/aF5Dhv4CFa - Ollie
看看我的修改。这实际上是关于个人偏好的问题。如果速度成为问题,你会想要进行基准测试并找到最快的解决方案,但除此之外,一切都完全相同。 - RyanScottLewis
2
这个答案中的正则表达式会泄露字符,从而导致错误的匹配结果,因为.通配符没有被转义。必须对它们进行转义才能正确地工作。 - the Tin Man
这已经被@BaroqueBobcat指出,但@the Tin Man是绝对正确的... .将需要转义... \. - Ollie

3

首先将要匹配的电子邮件和域名转换为小写,然后使用find_all正则表达式匹配。

您可以使用find仅检索第一个匹配的“规则”。

email = 'bob@luv.southwest.com'

domain_rules = [/craigslist.org/, /evite.com/, /ziprealty.com/, /alleyinsider.com/, /fedexkinkos.com/, /luv.southwest.com/, /fastsigns.com/, /experts-exchange.com/, /feedburner.com/]
user, domain = email.split('@').collect { |s| s.downcase }
p domain_rules.find_all { |rule| domain[rule] }

实际上,Regexp并不是必需品:

email = 'bob@luv.southwest.com'

matchable_domains = %w{ craigslist.org evite.com ziprealty.com alleyinsider.com fedexkinkos.com luv.southwest.com fastsigns.com experts-exchange.com feedburner.com }
user, domain = email.downcase.split('@')
p matchable_domains.find_all { |rule| matchable_domains.include?(domain) }

或者,你可以只使用正则表达式:

email = 'bob@luv.southwest.com'
regexp = /[A-Z0-9._%+-]+@(craigslist\.org|evite\.com|ziprealty\.com|alleyinsider\.com|fedexkinkos\.com|luv\.southwest\.com|fastsigns\.com|experts-exchange\.com|feedburner\.com)/

p regexp === email # => true
p regexp.match(email) # => #<MatchData "bob@luv.southwest.com" 1:"bob" 2:"luv.southwest.com">il

1
为什么不使用detect而不是find_all - Ryan Bigg
@Ryan,有什么区别吗? - AnApprentice
“detect”与“find”是相同的。http://rubydoc.info/stdlib/core/1.9.2/Enumerable:detect - RyanScottLewis
@c00lryguy 谢谢。我想知道为什么要使用 detect 而不是 find_all。 - AnApprentice
正则表达式模式在 . 通配符处泄漏,因此此答案存在问题。所有通配符都需要转义,\. - the Tin Man
显示剩余5条评论

2
无需使用正则表达式进行简单的字符串比较。
email = 'bob@luv.southwest.com'

domains = %w(CraigsList.org evite.com ZiPreAltY.com alleyinsider.com fedexkinkos.com luv.southwest.com fastsigns.com experts-exchange.com feedburner.com)

user, user_domain = email.split('@')

p domains.any? { |domain| domain.casecmp(user_domain).zero? }

String#casecmp函数执行不区分大小写的比较。


有趣。结果为0表示匹配成功,结果为1表示没有匹配。 - Joshua Pinter
@JoshuaPinter String#casecmp 返回 01-1,以匹配 <=> 的工作方式和排序的工作方式。 - mu is too short
1
@muistooshort 谢谢你的回复。我还发现可以使用 .casecmp?,它在匹配时返回 true,不匹配时返回 false,这似乎比 .zero? 更易读。 - Joshua Pinter

1

我看到你目前实现的一个问题是它会匹配像luvesouthwestlcom.com这样的域名,因为.可以匹配任何字符。你可以通过对你使用的所有url进行转义来解决这个问题,例如:

email = 'bob@luv.southwest.com'

domains = %w[craigslist.org evite.com ziprealty.com alleyinsider.com fedexkinkos.com luv.southwest.com fastsigns.com experts-exchange.com feedburner.com]

domain_rules = domains.map{|d| /#{Regexp.escape(d)}/i }
user, domain = email.split('@')

domain_rules.any? { |rule| domain.match(rule) }

此外,如果您只想查找完全匹配的内容,您并不需要使用正则表达式,只需检查电子邮件域是否包含您要查找的字符串之一即可。
email = 'bob@luv.southwest.com'

domains = %w[craigslist.org evite.com ziprealty.com alleyinsider.com fedexkinkos.com luv.southwest.com fastsigns.com experts-exchange.com feedburner.com]

user, domain = email.split('@')
domain.downcase! # lower cases the string in place

domains.any? { |rule| domain.include?(rule) }

这两种方法的问题在于它们会匹配任何包含完全相同字符串的内容,因此'craigslist.org'将匹配'nyc.craiglist.org''craigslist.org.uk'。如果您想要精确匹配,可以在将输入域名转换为小写后使用==。例如:

domains.any? { |rule| domain == rule }

1
你可以将电子邮件地址转换为小写。

0
你可以将规则作为简单的字符串传递,并动态构建正则表达式:
email = 'bob@luv.southwest.com'

domains = %w(craigslist.org evite.com ziprealty.com) # etc
user, domain = email.split('@').collect { |s| s.downcase }

p domains.any? { |d| domain.match(/#{d}/i) }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接