LINUX.ORG.RU

Как выдернуть из огромного файла только e-mail адреса?

 ,


1

1

Возникла адская задачка. Необходимо распарсить файл бэкапа БД, и выдернуть из него _только_ e-mail адреса. Формат разный, могут быть большие и маленькие буквы, _, -, точки - в общем, все возможные варианты. Адресов много, мусора ещё больше.

Формат БД абсолютно упоротый («Инфокуб», если кому интересно).

Вопрос: как это сделать с помощью perl или есть более удобные средства для этого? Объём файла - 440 мегабайт.

В RTFM не отправлять, спрашиваю потому, что надо сделать в ближайшие пару часов.

★★★★

часа на man grep и гугл должно хватить :)
а по факту - посмотри таблицы внимательно, там наверняка чонить в духе email = example@exp.com

tazhate ★★★★★
()
Ответ на: комментарий от tazhate

С grep получаю почему-то «Двоичный файл (стандартный ввод) совпадает».

И да, там нет ничего в видел e-mail.

Подписи выделены чёрным в notepad++, Но перед адресами стоят непонятные метки: перед одним NUL DC1 SI, перед другим NUL EM ETB и так далее. Вообще не вижу логики. Ну и выглядит это отвратно.

ekzotech ★★★★
() автор топика
Ответ на: комментарий от helios

На выходе пустой файл.

Вроде не бинарный, т.к. notepad++ в виндовс и gedit в linux открывают его (правда gedit зависает и тупит, но сам факт открытия файла имеет место).

ekzotech ★★★★
() автор топика
Ответ на: комментарий от ekzotech

grep -U -o -E «[0-9A-Za-z][0-9A-Za-z._-]+\@[0-9A-Za-z._-]+» file.db

по желанию, можешь для -E воткнуть регекс от будиста

ananas ★★★★★
()

В RTFM не отправлять, спрашиваю потому, что надо сделать в ближайшие пару часов.

почему тогда не запостил маленький кусочек БД? Что-бы было на чём проверять.

drBatty ★★
()

Вопрос: как это сделать с помощью perl или есть более удобные средства для этого? Объём файла - 440 мегабайт.

на sed будет быстрее в разы. (там более дубовые RE без возврата)

drBatty ★★
()
Ответ на: комментарий от helios

Упс, точно. Последняя версия сработала, дубли потом убрал, пропустив результат через grep. Спасибо большое!

ekzotech ★★★★
() автор топика
Ответ на: комментарий от drBatty

почему тогда не запостил маленький кусочек БД? Что-бы было на чём проверять.

Инфокуб же - непонятно что там и как.

Да и не копируется - там ад какой-то.

И потом, perl уже всё сделал =)

ekzotech ★★★★
() автор топика
Ответ на: комментарий от xtraeft

Хм, а я отдельно пропускал через sort | uniq.

ekzotech ★★★★
() автор топика
Ответ на: комментарий от drBatty

просто это очень долго через жопу кошки в перловку загонять...

cat test | wc -l
297327
time cat test | perl -e 'while(<>) { $_ =~ s/a/b/g; print; }' > /dev/null
real 0m0.317s
time sed «s/a/b/g» test > /dev/null
real 0m0.258s

redgremlin ★★★★★
()
Последнее исправление: redgremlin (всего исправлений: 1)
Ответ на: комментарий от redgremlin

real 0m0.317s

всё зависит от скорости чтения и скорости обработки. Если время упирается в чтение(как у тебя), то каждая строка обрабатывается _быстрее_, чем читается. Посему, общая скорость будет равна скорости чтения. Ну а с твоим регэкспом время вообще около нуля. IRL если взять большой дамп, со строчками в ~60K, и с регекспами, которые что-то _изменяют_, то разница получается значительной.

drBatty ★★
()
Ответ на: комментарий от drBatty

Ну вот кусок пасты. Как выдернуть что-то другое - я хз. Первые 8 тысяч строк описывается местами структура, а местами и вовсе непонятно что. А потом идёт дикая каша.

Из любого текстового редактора это просто невозможно скопировать. Ну или я не знаю как.

дело ваше. просто это очень долго через жопу кошки в перловку загонять...

Да ладно, 30 секунд и готово. На выходе порядка 350 e-mail адресов (после дедупликации).

ekzotech ★★★★
() автор топика
Ответ на: комментарий от drBatty

взять большой дамп, со строчками в ~60K

Ха! Это большой дамп? Вот то, что сейчас разбиралось - имеет 3,3 млн строк, и до 1000 символов в строке (пока самая большая строка - 764 символа). Сейчас ради интереса замеряю реальное время.

ekzotech ★★★★
() автор топика
Ответ на: комментарий от ekzotech

Ну вот:

ekzotech@snsv:~$ time cat 1212261543ic.gbk | perl -e 'while($str = <>){ print "$1\n" while $str =~ /\G.*?([a-z0-9_\-\.]+@[a-z0-9_\-\.]+\.\w{2,4})/gic }' > emails.txt

real	1m9.735s
user	1m10.286s
sys	0m0.863s

Хотя да, с 30 секундами я погорячился, вышло дольше.

ekzotech ★★★★
() автор топика
Ответ на: комментарий от ekzotech

Ну вот кусок пасты.

я не вижу тут ни одного адреса.

Из любого текстового редактора это просто невозможно скопировать. Ну или я не знаю как.

sed '...' file.txt

потом мышкой скопипастить.

Да ладно, 30 секунд и готово.

а... ну тогда ладно...

взять большой дамп, со строчками в ~60K

Ха! Это большой дамп? Вот то, что сейчас разбиралось - имеет 3,3 млн строк, и до 1000 символов в строке (пока самая большая строка - 764 символа). Сейчас ради интереса замеряю реальное время.

ты не понял - это несколько тысяч мб дампа, где _каждая_ строчка примерно 60000байт. И это ещё не большой, а так, средний. а твой - вообще мелочь.

drBatty ★★
()
Ответ на: комментарий от redgremlin

Нет. man tmpfs. time cat test > /dev/null даёт несколько тысячных секунды.

под «чтением» я также понимаю всю пред- и пост- обработку строки. Там немного, но всё же в разы меньше, чем обработка регекспа /a/. Ну а cat >/dev/null только читает файл ЕМНИП. В отличие от создания PIPE и передачи через него данных.

Короче - надо тестировать на больших строчках со сложной обработкой. Часто sed получается в разы быстрее, ибо все регекспы в sed обрабатываются _всегда_ за один проход (это не только быстро, но и плохо, ибо сложные RE писать неудобно, а иногда и невозможно, приходится делать сложные циклы, и в итоге иногда получается проигрыш по сравнению с PCRE).

drBatty ★★
()
Ответ на: комментарий от drBatty

регекспа /a/

Не /a/, а s/a/b/g, для чего он должен перебрать всю строку посимвольно. В test я тупо с'cat'ал все сорцы одного проекта. Попробовал еще сорцы mplayer также проверить (это с миллион строк кода), получилось 0.940s perl и 0.794s sed. Могу еще на 40 гиговом дампе от постгреса проверить (завтра и с харда, 40 гигов на tmpfs у меня нет), но, думаю, будет также не более 20% разницы.

redgremlin ★★★★★
()
Ответ на: комментарий от redgremlin

Не /a/, а s/a/b/g, для чего он должен перебрать всю строку посимвольно.

а любое RE всю строку перебирает. и те, что в glibc и тем более PCRE. Даже если это /./

В test я тупо с'cat'ал все сорцы одного проекта. Попробовал еще сорцы mplayer также проверить (это с миллион строк кода), получилось 0.940s perl и 0.794s sed.

с мелкими строками (~50 символов) разницы практически нет. Заметно только на больших строках (скомпилированные выражения очень быстро применяются к строке. Причём, насколько я понимаю, если это обычное RE, то выполняется оно кодом из glibc. Смысл сравнивать одно и тоже?)

Могу еще на 40 гиговом дампе от постгреса проверить (завтра и с харда, 40 гигов на tmpfs у меня нет), но, думаю, будет также не более 20% разницы.

сравнивали как-то на UFO - перловка победила. Она по дефолту без UTF-8 работала. Если и то и другое с/без UTF-8 - одно и тоже.

drBatty ★★
()
3 июля 2013 г.
Ответ на: комментарий от vasilenko

Забыл дописать, что работает только от рута, ога.

P.S. «Патч Бармина».

ekzotech ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.