Извлечение определенной информации из журналов

Я извлек следующую информацию из необработанных журналов, используя следующую команду:

echo -e "Timestamp\t\tEmailTo:\t\tEmailFrom:\t\t\t\t\tIPAddress:\tErrorCodes:" && sed -n -e 's/.*\([0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9]*\) .*\([0-9][0-9]:[0-9][0-9]:[0-9][0-9]*\).*/\1 \2 /p' logs

Вывод:

 Timestamp EmailTo: EmailFrom: IPAddress: ErrorCodes: 2017-01-02 12:50:00 2017-01-02 13:10:25 

Необработанные журналы:

 2017-01-02 12:50:00 1cNxNS-001NKu-9B == redhat_619@yahoo.com R=dkim_lookuphost T=dkim_remote_smtp defer (-45) H=mta6.am0.yahoodns.net [98.138.112.38]: SMTP error from remote mail server after MAIL FROM:<web@pharma.com> SIZE=1772: 421 4.7.0 [TSS04] Messages from 192.168.1.269 temporarily deferred due to user complaints - 4.16.55.1; see https://help.yahoo.com/kb/postmaster/SLN3434.html 2017-01-02 13:10:25 1cNxhD-001VZ3-0f == infopharma@yahoo.com (info@pharma.com) <info@pharma.com> R=lookuphost T=remote_smtp defer (-45) H=mta7.am0.yahoodns.net [98.138.112.34]: SMTP error from remote mail server after MAIL FROM:<red@nic.net.org> SIZE=87839: 500 5.9.0 [TSS04] Messages from 192.168.1.269 temporarily deferred due to user complaints - 4.16.55.1; see https://help.yahoo.com/kb/postmaster/SLN3434.html 

Но я не могу извлечь другую информацию, в которой я нуждаюсь; это должно выглядеть так:

 Timestamp EmailTo: mailFrom: IPAddress: ErrorCodes: 2017-01-02 12:50:00 redhat_619@yahoo.com web@pharma.com 192.168.1.269 421 4.7.0 2017-01-02 13:10:25 infopharma@yahoo.com red@nic.net.org 192.168.1.269 500 5.9.0 

Как я могу извлечь всю информацию с помощью sed ?

  • Исключение отдельных строк от перенаправления
  • bash while / read loop ведет себя по-разному в виртуальной машине на основе mips / musl / busybox
  • Создать таблицу с частотой уникальных имен, полученных из нескольких CSV-файлов
  • Вызов сценария не по тому же пути
  • Случайные аргументы (содержащие цветовые коды) из массива
  • Запрос Bash на запись в каждый каталог под некоторым путем и запуск команды, когда он внутри?
  • Создание имени базы данных MySQL с использованием переменной с даты
  • Создание сценария оболочки, который анализирует и перенаправляет число в следующую команду?
  • 2 Solutions collect form web for “Извлечение определенной информации из журналов”

    Вы можете попробовать это выражение sed :

     sed -e 's/^\(.* .* \).* .*== \([^ ]* \).*MAIL FROM:<\([^ ]*\)> [^ ]* \([0-9 .]*\)\[.*Messages from \([^ ]*\).*$/\1\t\2\t\3\t\5\t\4/' 

    Это работает для меня с вашим примером.

    объяснение

    Это выражение sed содержит только одну команду – s/.../.../ .

    Первая часть s/// :

     '^\(.* .* \)' -- Timestamp, two first space-separated blocks of text, \1. '.* .*== ' -- Uninteresting text after timestamp. '\([^ ]* \)' -- Block of test between spaces, first email address, \2. '.*MAIL FROM:<' -- Position before second email. '\([^ ]*\)>' -- Second email addr, non-space characters, ended by '>', \3. ' [^ ]* ' -- SIZE=...: '\([0-9 .]*\)\[' -- Error codes: digits, spaces and dots ended by '[', \4. '.*Messages from ' -- Position before IP. '\([^ ]*\)' -- Non-space characters, ended by space, IP. \5. '.*$' -- Text before end of string, not interesting. 

    Как вы можете видеть, это просто прямое описание сырых журналов, нет ничего интересного.

    Вторая часть s/// просто помещает \N в правильном порядке с \t (символ табуляции) в качестве разделителя.

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

    Во всяком случае, это использует блок BEGIN для настройки выбранных переменных и форматированную строку для печати перед отображением заголовка. Время и EmailTo предсказуемы, поэтому можно использовать пронумерованные поля ( $1 , $2 и $5 ) перед тремя наборами регулярных выражений, которые являются очень грубыми. Любые предложения по улучшению будут оценены!

     awk 'BEGIN { from=""; ip=""; error=""; fstr="%-24s%-24s%-40s%-16s%s\n"; printf(fstr, "Timestamp:", "EmailTo:", "EmailFrom:", "IPAddress:", "ErrorCodes:"); } { for (i=6; i<NF; i++) { # From Address if ($i ~ /FROM:<[^ ]*>/) from=substr($i, 7, length($i)-7); # Errors found in two adjacent fields. if ($(i-1) ~ /[[:digit:]]{3}/ && $i ~ /[[:digit:]]\.[[:digit:]]\.[[:digit:]]/) error=$(i-1) " " $i; # From address after predictable string. if ($(i-2) " " $(i-1) == "Messages from" && $i ~ /[[:digit:].]{7,15}/) ip=$i; } printf(fstr, $1" "$2, $5, from, ip, error); }' logs 
    Linux и Unix - лучшая ОС в мире.