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

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

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: Это добавит пробел в начале вывода

  • Объяснение для 'sed'
  • grep: Как найти консоль для закрытия?
  • Как именно создать сценарий sed и использовать его для редактирования файла?
  • разделить линию на основе пробела и удалить вторую часть
  • Вытягивание IP-адреса из команды ping с помощью sed?
  • Использовать sed для добавления символа в n-й позиции соответствующей строки
  • Печатать начало и конец между двумя шаблонами, исключая конец диапазона
  • Заменить значения в определенном разделе в файле
  • Grepping для блока текста с частями, которые могут быть необязательными
  • Нужно преобразовать столбец timestamp unix epoch в каждую строку с помощью sed или awk
  • как я могу использовать sed для замены списков, начинающихся с (*) в файле
  • Объединение двух файлов, по одному столбцу за раз
  • Linux и Unix - лучшая ОС в мире.