Извлечь конкретную информацию из журналов

С gnu sed :

sed -n -e ' /.*#$/ { p; h; b; };' \
       -e '{ H; x; s/[\n[:blank:]]\+/ /; p; s/\(.*#\).*/\1/; h; }' \
        file.txt

Общая идея состоит в том, чтобы сохранить строку ... # в удерживаемом пространстве и добавить ее в начало строки при последующих не ... # строк (в пространстве шаблона).

1
03.01.2017, 17:19
2 ответа

Вы можете попробовать это выражение 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 (символ табуляции) в качестве разделителя.

2
27.01.2020, 23:34

У меня нет большого опыта работы с 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
0
27.01.2020, 23:34

Теги

Похожие вопросы