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

Должен ли этот вопрос переноситься в 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 может выполнить всю работу.

  • Как распечатать только первое совпадение из каждой строки?
  • Как я могу найти и заменить только в том случае, если совпадение составляет целое слово?
  • sed regex для группы захвата между разделителями
  • Заставить sed запрашивать подтверждение перед каждой заменой?
  • Заменить соответствия многострочной строкой с помощью sed
  • Как использовать переменные в команде sed
  • найти строки, которые не заканчиваются на «rpms» с sed
  • 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 - лучшая ОС в мире.