You are here

Решение: средствами Sed и Cut, если нам элементарно надо вырезать Email из строки

Задача: мы хотим проанализировать  типичный лог(журнал) почтового сервера и нам надо получить почтовые адреса при вхождении определённого слова, например мне нужны все адреса в строках, где есть вхождение слов: "Mailbox disabled for this recipient".

Решения: Что я делаю, для начала выводим файл лога(речь конечно же про *nix системы, хотя подобные программки должны существовать и для Windows)

cat /var/log/maillog
^^ - выведеет файд /var/log/maillog на экран

grep "Mailbox disabled for this recipient"
^^^ -
отсортирует строчки содержащие сочетание слов "Mailbox disabled for this recipient".

Эти две команды должны применяться в потоковом контейнере программ значок "|", а конкретно вот так:

cat /var/log/maillog | grep "Mailbox disabled for this recipient"

В ответ вы получите что-то типа: 
Feb  7 12:39:04 microsoft sm-mta[72873]: s17sffd2Ed3jJ072873: ruleset=check_rcpt, arg1=<vasya@microsoft.com>, relay=segment-223-30.sify.net [223.30.12.34] (may be forged), reject=550 5.2.1 <vasya@microsoft.com>... Mailbox disabled for this recipient

Тут встаёт ЭЛЕМЕНТАРНАЯ задача, обрезать всё до символа "<" и после символа ">", но элементарная она для лютых админов, прочтиавших немало руководств, по утилитам Sed, Cut, Awk и т.п. Для обычного же пользователя(да и для необычного) на просторах интернета найти решение не так легко, конкретно под эту тривиальную задачу. И благо я спустя час другой нашёл решения, я их тут выложу, чтобы в поисковике при правильном запросе, вы попадали на готовенькое :), удачи вам!

Итак обрезать ДО символа <
sed 's|.*<||'
cat /var/log/maillog | grep "Mailbox disabled for this recipient" | sed 's|.*<||'
или          
cut -d"<" -f2
cat /var/log/maillog | grep "Mailbox disabled for this recipient" | cut -d"<" -f2

Но получили мы строчку типа:
"vasya@microsoft.com>, relay=segment-223-30.sify.net [223.30.12.34] (may be forged), reject=550 5.2.1 <vasya@microsoft.com>... Mailbox disabled for this recipient"

Это уже хорошо, но пока ещё не готово. Теперь будем искать способ, удалить этими же средствами, всё ПОСЛЕ символа ">".

sed -r 's/>.+//'
cat /var/log/maillog | grep "Mailbox disabled for this recipient" | sed 's|.*<||'|sed -r 's/>.+//'

^^^^ Вот так можно добиться обрезания в файле maillog всёх букв до символа < и всех букв после символа >. 

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

Надеюсь я кому-нибудь помог.

P.S. потом как-нибудь разберусь и опишу, что значит каждый параметр, но это будет позже. Пока пользуйтесь готовеньким. 

Comments

Добавлю так же, что например если этот список потом надо преобразовать в одну строчку, например с разделителем в виде запятой, то можно использовать такую штуку как "tr".
tr \\n \,

То есть вместо:
vasya@pukin.com
bill@geytc.ru
cat@bobcat.org
получим: vasya@pukin.com, bill@geytc.rucat@bobcat.org

Спасибо большое, это как раз то что требовалось!

Наслаждайся :-)

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

Спасибо, добрый человек. так же, как и ты, оказался в такой ситуации. твое решение, наверное, единственное, что мне подошло.

в случае если надо удалить в строке все после символа "/" - его экранировать надо? какими кавычками?

Примеры из темы - рабочие.

Проверялись в FreeBSD интерпретатор SH. В других может работать иначе, потому с ходу не зная системы подсказать не смогу, но вероятно это легко ищется по вашей системе. Если не смогли, чирканите, где делаете, я попробую помочь. 

Мне нравятся sed backreference - удобно и гибко

echo "Feb 7 12:39:04 microsoft sm-mta[72873]: s17sffd2Ed3jJ072873: ruleset=check_rcpt, arg1=<vasya1@microsoft.com>, relay=segment-223-30.sify.net [223.30.12.34] (may be forged), reject=550 5.2.1 <vasya2@microsoft.com> Mailbox disabled for this recipient" | sed 's|^[^<]*<\([^>]*\)>.*$|\1 |'

первый e-mail в строке     | sed 's|^[^<]*<\([^>]*\)>.*$|\1 |'

vasya1@microsoft.com

второй e-mail в строке     | sed 's|^.*<\([^>]*\)>.*$|\1 |'

vasya2@microsoft.com

оба e-mail    | sed 's|^.*<\([^>]*\)>.*<\([^>]*\)>.*$|\1 \2 |'

vasya1@microsoft.com vasya2@microsoft.com

оба e-mail плюс дата и ip адрес      | sed 's|^\([^:]*\) .*<\([^>]*\)>.*\[\([^]]*\)].*<\([^>]*\)>.*$|\1 \2 \3 \4 |'

Feb 7 vasya1@microsoft.com 223.30.12.34 vasya2@microsoft.com

пробел для определенности и читаемости заменил на \s

| sed 's|^\([^:]*\)\s.*<\([^>]*\)>.*\[\([^]]*\)].*<\([^>]*\)>.*$|\1 ip=\3 - \2 \4 |'

Feb 7 ip=223.30.12.34 - vasya1@microsoft.com vasya2@microsoft.com

Add new comment

Редактор TinyMCE

  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <br> <img> <hr> <blockquote> <iframe>
  • Web page addresses and e-mail addresses turn into links automatically.

Чистый текст

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.