로그에서 여러 줄 필터링

로그에서 여러 줄 필터링

이 질문을 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입니다.

로그 항목을 필터링(grep은 행만 필터링)하는 빠른 명령(sed/grep/awk/etc 조합 사용)을 원합니다. 예를 들어 "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가 모든 작업을 수행할 수도 있습니다.

답변1

여러 악기를 섞을 필요가 없습니다. 과제는 sed통과만 가능

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

답변2

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 = '';
}

답변3

답변을 바탕으로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

참고: 이렇게 하면 출력 시작 부분에 공백이 추가됩니다.

관련 정보