Фильтрация многострочных строк из журнала

Должен ли этот вопрос переноситься в stackoverflow?

Мне часто приходится читать файлы журналов, созданные java-приложениями, используя log4j. Обычно зарегистрированное сообщение (назовем его записью журнала) охватывает несколько строк. Пример:

INFO 10:57:01.123 [Thread-1] [Logger1] This is a multi-line text, two lines DEBUG 10:57:01.234 [Thread-1] [Logger2] This entry takes 3 lines line 2 line 3 

Обратите внимание, что каждая запись в журнале начинается с новой строки, и самое первое слово из этой строки – TRACE, DEBUG, INFO или ERROR и по крайней мере одно место. Здесь имеется 2 записи в журнале, первая – в миллисекундах 123, другая – в миллисекундах 234.

Мне нужна быстрая команда (используя комбинацию sed / grep / awk / etc) для фильтрации записей журнала (grep только фильтрует строки), например: удалите все записи журнала, содержащие текст «Logger2».

Я рассмотрел следующие преобразования:

1) соединяют линии, принадлежащие тем же лог-элементам со специальной последовательностью символов (например: ##); таким образом, все записи журнала будут занимать ровно одну строку

 INFO 10:57:01.123 [Thread-1] [Logger1] This is a multi-line##text, two lines DEBUG 10:57:01.234 [Thread-1] [Logger2] This entry takes 3 lines##line 2##line 3 

2) grep
3) разделите строки назад (т.е.: замените ## на \ n)

У меня были проблемы на шаге 1 – у меня недостаточно опыта с sed.

Возможно, 3 шага выше не требуются, возможно, sed может выполнить всю работу.

  • сравнение 2 списков с дополнительными данными для печати
  • Удалить строку с пробелами и цитатами из xml-файла
  • Заменяйте символы по определенному индексу, отсчитываемому сзади
  • Справка по использованию Shell
  • Невозможно выполнить замену в программе sed
  • Удалить комментарии в файле C
  • Удалить строки из файла в зависимости от строк, найденных в другом файле
  • Удалить строки до заголовка с помощью sed
  • 3 Solutions collect form web for “Фильтрация многострочных строк из журнала”

    Нет необходимости смешивать многие инструменты. Задача может выполняться только sed

     sed '/^INFO\|^DEBUG\|^TRACE\|^ERROR/{ /Logger2/{ :1 N /\nINFO\|\nDEBUG\|\nTRACE\|\nERROR/!s/\n// $!t1 D } }' log.entry 

    perl-фильтр для многострочных записей журнала (отметка начала записи)

    Используйте следующий скрипт perl как рабочий прототип.
    Использование script_path regular_expression log_files
    например script_path "line \d" log_file_1 log_file_2

     #!/usr/bin/perl $pattern = qr/(?^s)$ARGV[0]/; shift; # process filtering expression # (?^s) - treats matched string as single line my $line = ''; # accumulates current log file record/paragraph while(<>) { if( /^(TRACE|DEBUG|INFO|ERROR) /o ) { # start of new record &flush; # flush/print previous recors } $line.=$_; } &flush; exit; sub flush { local $_ = $line; if( length($_) and /$pattern/ ) { print; } $line = ''; } 

    Основываясь на одном ответе на https://stackoverflow.com/questions/9605232/merge-two-lines-into-one, похоже, это соответствует счету

     #!/usr/local/bin/bash PATTERN1='TRACE *'; PATTERN2='DEBUG *'; PATTERN3='INFO *'; PATTERN4='ERROR *'; LINEOUT="" while read line; do case $line in $PATTERN1) echo $LINEOUT LINEOUT="$line" ;; $PATTERN2) echo $LINEOUT LINEOUT="$line" ;; $PATTERN3) echo $LINEOUT LINEOUT="$line" ;; $PATTERN4) echo $LINEOUT LINEOUT="$line" ;; "") LINEOUT="" ;; *) LINEOUT="$LINEOUT ## $line" ;; esac done echo $LINEOUT 

    NB: Это добавит пробел в начале вывода

    Linux и Unix - лучшая ОС в мире.