Посмотрите на методы Руби Regexp.union
и Regexp.escape
. Они позволяют легко создавать шаблоны регулярных выражений на основе текстовых или регулярных выражений.
Это из union
документов:
Возвращает объект Regexp, который является объединением заданных шаблонов, то есть будет соответствовать любой его части. Шаблоны могут быть объектами Regexp, в этом случае их параметры будут сохранены, или Strings. Если шаблоны не указаны, возвращает / (?!) /. Поведение не определено, если какой-либо шаблон содержит захват.
Regexp.union #=> /(?!)/
Regexp.union("penzance") #=> /penzance/
Regexp.union("a+b*c") #=> /a\+b\*c/
Regexp.union("skiing", "sledding") #=> /skiing|sledding/
Regexp.union(["skiing", "sledding"]) #=> /skiing|sledding/
Regexp.union(/dogs/, /cats/i) #=> /(?-mix:dogs)|(?i-mx:cats)/
И из escape
документов:
Исключает любые символы, которые будут иметь особое значение в регулярном выражении. Возвращает новую экранированную строку или self, если экранированные символы отсутствуют. Для любой строки будет выполнено Regexp.new (Regexp.escape (str)) = ~ str.
Regexp.escape('\*?{}.') #=> \\\*\?\{\}\.
Это отправная точка:
patterns = [
/.+?\+.+?@/
]
strings = [
'do-not-reply', 'support', 'test', 'service', 'tips', 'twitter', 'alerts', 'survey',
'craigslist.org'
]
regex = Regexp.union(
*patterns,
*strings.map{ |s|
Regexp.new( Regexp.escape("#{ s }@"), Regexp::IGNORECASE ) }
)
pp regex
>> /(?-mix:.+?\+.+?@)|(?i-mx:do\-not\-reply@)|(?i-mx:support@)|(?i-mx:test@)|(?i-mx:service@)|(?i-mx:tips@)|(?i-mx:twitter@)|(?i-mx:alerts@)|(?i-mx:survey@)|(?i-mx
Применяя вышеизложенное:
sample_email_addresses = %w[
user
user+foo
do-not-reply
support
service
tips
twitter
alerts
survey
].map{ |e| e << '@host.com' }
pp sample_email_addresses.map{ |e| [e, !!e[regex]] }
>> [["user@host.com", false],
>> ["user+foo@host.com", true],
>> ["do-not-reply@host.com", true],
>> ["support@host.com", true],
>> ["service@host.com", true],
>> ["tips@host.com", true],
>> ["twitter@host.com", true],
>> ["alerts@host.com", true],
>> ["survey@host.com", true]]
Выходные данные показывают список, содержащий каждый проверенный адрес. true
означает, что они вызвали попадание в регулярное выражение, что означает, что что-то не так, и false
означает, что они были чисты и считались безопасными.
Если вам нужны только те, которые потерпели неудачу, то есть соответствуют регулярному выражению:
pp sample_email_addresses.select{ |e| e[regex] }
>> ["user+foo@host.com",
>> "do-not-reply@host.com",
>> "support@host.com",
>> "service@host.com",
>> "tips@host.com",
>> "twitter@host.com",
>> "alerts@host.com",
>> "survey@host.com"]
Если вы хотите, чтобы только те, которые прошли, то есть, не вызывали попадание в регулярное выражение:
pp sample_email_addresses.reject{ |e| e[regex] }
>> ["user@host.com"]