Найти адреса электронной почты в большом потоке данных - PullRequest
4 голосов
/ 11 февраля 2009

ЕЩЕ НЕ РЕШЕНО: ( [11 февраля]

У меня большой текстовый файл, полный случайных данных, и я хочу извлечь из него все адреса электронной почты.

Я хотел бы сделать это в Ruby, с псевдокодом, подобным этому:

monster_data_string = "asfsfsdfsdfsf  sfda **joe@example.com** sdfdsf"
monster_data_string.match(EMAIL_REGEX)

Кто-нибудь знает, какое регулярное выражение электронной почты Ruby я бы использовал для этого?

Пожалуйста, имейте в виду, что я ищу Ruby ответ на этот вопрос. Я уже пробовал многочисленные регулярные выражения, найденные поиском в Google, но большинство из них приводят к ошибкам во время выполнения Ruby, в которых говорится, что такие символы, как «+» и «», являются недопустимыми / нераспознанными.

Я уже пробовал:

monster_data_string.match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)

но я получаю ошибки Ruby, в которых говорится, что "+" является недопустимым символом

Заранее спасибо

Ответы [ 6 ]

14 голосов
/ 21 сентября 2009

Смотреть это ...

f =  File.open("content.txt")
content = f.read    
r = Regexp.new(/\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/)     
emails = content.scan(r).uniq                                    
puts YAML.dump(emails)    
3 голосов
/ 12 февраля 2009

Если вы получаете сообщение об ошибке о том, что + или * недопустимы в регулярных выражениях, вы делаете что-то очень неправильное. Это правильное регулярное выражение в Ruby, хотя это не то, что вам нужно:

/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i

Во-первых, вы не хотите привязывать регулярное выражение к началу и концу строк (^ и $), если вы пытаетесь извлечь адреса из «случайного» текста. Но как только вы избавитесь от якорей, ваше регулярное выражение будет соответствовать **joe@example.com в вашей тестовой строке, что, я полагаю, вам не нужно. Это регулярное выражение из Regular-Expressions.info работает лучше, но прочитайте эту страницу для получения советов по настройке в соответствии с вашими конкретными потребностями.

/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i

Наконец (и вы, возможно, уже знаете это), вы не захотите использовать метод match(), потому что он найдет только первое совпадение 1016 *. Попробуйте scan() вместо.

1 голос
/ 12 февраля 2009

Чтобы попытаться помочь вам добраться (хотя и не очень элегантно, я признаю):

Я думаю, что начальный и конечный якоря (^ и $) не помогают. Вы также можете отфильтровать звездочки?

irb(main):001:0> mds = "asfsfsdfsdfsf  sfda **joe@example.com** sdfdsf"
  => "asfsfsdfsdfsf  sfda **joe@example.com** sdfdsf"
irb(main):003:0> mds.match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
  => nil
irb(main):004:0> mds.match(/([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})/i)
  => #<MatchData "**joe@example.com" 1:"**joe" 2:"example.com">
irb(main):005:0> mds.match(/([^@\s*]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})/i)
  => #<MatchData "joe@example.com" 1:"joe" 2:"example.com">
1 голос
/ 12 февраля 2009

Какие сообщения об ошибках во время выполнения вы получаете? Это относится к регулярным выражениям как к недействительным или разрывается из-за слишком большой целевой строки?

1 голос
/ 11 февраля 2009

Учитывая, что невозможно проанализировать каждый действительный адрес электронной почты с помощью регулярного выражения, у вас есть два варианта:

Создайте регулярное выражение, которое соответствует как можно большему количеству действительных адресов электронной почты, и учитывайте тот факт, что некоторые действительные, но редко используемые формы адресов электронной почты могут быть упущены.

или

Создайте регулярное выражение, которое сопоставляет все, что «может быть» адресом электронной почты, а затем соответствует ложным срабатываниям

Я использую второй подход, чтобы отсеять явно неправильные адреса электронной почты при проверке адреса электронной почты при регистрации пользователя на веб-странице.

Получено из Ruby Cookbook, в котором есть очень хороший раздел о проверке адреса электронной почты:

valid = '[^ @]+'
/^#{valid}@#{valid}\.#{valid}/

По-видимому, существует регулярное выражение Perl в 6343 символа, написанное Полом Уорреном, которое очень хорошо работает и работает в Ruby, но даже это не является надежным (я думаю, что это также может иметь некоторые последствия для производительности).

0 голосов
/ 25 сентября 2010

Еще лучше,

require 'yaml'

content = "asfsfsdfsdfsf  sfda **joe@example.com.au** sdfdsf cool_me@example.com.fr"

r = Regexp.new(/\b([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+?)(\.[a-zA-Z.]*)\b/)     
emails = content.scan(r).uniq                                    
puts YAML.dump(emails)

даст вам

    ---
    - - joe
      - example
      - .com.au
    - - cool_me
      - example
      - .com.au
...