Использование grep для поиска всех электронных писем

Как правильно построить регулярное выражение для программы "grep" linux, чтобы найти все сообщения электронной почты, скажем каталог /etc? В настоящее время мой script выглядит следующим образом:

grep -srhw "[[:alnum:]]*@[[:alnum:]]*" /etc

Он работает нормально - см. некоторые из писем, но когда я его изменяю, чтобы поймать один или несколько символов раньше и после знака "@"...

grep -srhw "[[:alnum:]][email protected][[:alnum:]]+" /etc

.. он вообще перестает работать

Кроме того, он не ловит электронные письма формы "[email protected]"

Справка!

Ответы

Ответ 1

Вот еще один пример

grep -Eiorh '([[:alnum:]_.-][email protected][[:alnum:]_.-]+?\.[[:alpha:].]{2,6})' "[email protected]" * | sort | uniq > emails.txt

Этот вариант работает с доменами 3 уровня.

Ответ 2

grep требуется большая часть специальных символов регулярного выражения для экранирования - включая +. Вы хотите сделать одно из этих двух:

grep -srhw "[[:alnum:]]\[email protected][[:alnum:]]\+" /etc

egrep -srhw "[[:alnum:]][email protected][[:alnum:]]+" /etc

Ответ 3

Я изменил ваше регулярное выражение, чтобы включить пунктуацию (например.-_ и т.д.), изменив ее на

egrep -ho "[[:graph:]][email protected][[:graph:]]+"

Это все еще довольно чисто и соответствует... ну, и все, что угодно с @в нем, конечно. Также домены третьего уровня также обращаются к "%" или "+" в них. См. http://www.delorie.com/gnu/docs/grep/grep_8.html для хорошей документации по используемому классу символов.

В моем примере адреса были окружены белым пространством, что упрощало сопоставление. Если вы, например, grep через журнал почтового сервера, можете добавить < > чтобы он соответствовал только адресам:

egrep -ho "<[[:graph:]][email protected][[:graph:]]+>"

@thomas, @glowcoder и @oedo все правы. RFC, который определяет, как адрес электронной почты может выглядеть, довольно забавно. (Я использовал GNU grep 2.9 выше, включенный в Ubuntu).

Также ознакомьтесь с версией zpea ниже, она должна сделать для менее согласованного с триггером совпадения.

Ответ 4

Я использовал это для фильтрации адреса электронной почты , идентифицированного символом 'at', и выделенного пробелами в тексте:

egrep -o "[^[:space:]][email protected][^[:space:]]+" | tr -d "<>"

Конечно, вы можете использовать grep -E вместо egrep (расширенный grep). Обратите внимание, что команда tr используется для удаления типичных разделителей электронной почты.

Ответ 5

grep -E -o -r "[A-Za-z0-9][A-Za-z0-9._%+-][email protected][A-Za-z0-9][A-Za-z0-9.-]+\.[A-Za-z]{2,6}" /etc

Это адаптировано из ответа, который изначально не был моим, но я нашел его очень полезным. Это отсюда:

http://www.shellhacks.com/en/RegEx-Find-Email-Addresses-in-a-File-using-Grep

Они предлагают:

grep -E -o -r "\b[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" /etc

Но у него есть определенные ложные срабатывания, такие как "+ person.. @example.com" или "person @.. com", а ограничения пробелов пропускают такие вещи, как "mailto: [email protected]" (не технически электронная почта, но содержит один); поэтому я немного изменил его.

(Делайте то, что хотите, с параметрами grep, я их не очень хорошо знаю)

Ответ 6

Эта рекурсивная работа отлично подходит для меня:

grep -rIhEo "\b[a-zA-Z0-9.-][email protected][a-zA-Z0-9.-]+\.[a-zA-Z0-9.-]+\b" /etc/*

Ответ 7

Просто хотел упомянуть, что небольшая вариация этого отлично подходит для захвата упоминаний о вещах вроде twitter tweets:

grep -Eiorh '(@[[:alnum:]_.-]+)' "[email protected]" * | sort | uniq -c