Unix 명령을 사용하여 파일 구문 분석

Unix 명령을 사용하여 파일 구문 분석

저는 Unix를 처음 접했고 분석해야 할 로그 파일이 있습니다. 다음은 내 샘플 로그 파일입니다.

Container:container_e182_1234
=============================
LogType:container-localizer-syslog
Log Upload Time :Thu Jun 25 12:24:45 +0100 2020
LogLength:0
Log Contents:

LogType:stderr
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:3000
Log Contents:
20/06/25 12:19:33 INFO datasources.FileScanRDD: Reading File path: hdfs://bpaiddev/dev/data/warehouse/clean/falcon/ukc/
20/06/25 12:19:39 ERROR Exception found
java.io.Exception:Not initiated
    at.apache.java.org.Exception(132)
20/06/25 12:19:40 INFO executor.EXECUTOR: Finished task 18.0 in stage 0.0 (TID 18),18994 bytes result sent to driver.
20/06/25 12:20:41 WARN Warning as the node is accessed without started
 
LogType:stdout
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:

Container:container_e182_1234
=============================
LogType:container-localizer-syslog
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:
    
LogType:stderr
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:3000
Log Contents:

LogType:stdout
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:

예상 출력

stderr
Thu Jun 25 12:24:52 +0100 2020
3000
20/06/25 12:19:39 ERROR Exception found
java.io.Exception:Not initiated
    at.apache.java.org.Exception(132)
20/06/25 12:20:41 WARN Warning as the node is accessed without started

출력에는 ERROR, WARN 및 위의 기타 세부정보만 포함되어야 합니다.

로그 파일:

Container:container_e182_1234
=============================
LogType:container-localizer-syslog
Log Upload Time :Thu Jun 25 12:24:45 +0100 2020
LogLength:0
Log Contents:

LogType:stderr
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:3000
Log Contents:
20/06/25 12:19:33 INFO datasources.FileScanRDD: Reading File path: hdfs://bpaiddev/dev/data/warehouse/clean/falcon/ukc/masked_data/parquet/FRAUD_CUSTOMER_INFORMATION/rcd_crt_dttm_yyyymmdd=20200523/part-0042-ed52abc2w.c000.snapp.parquet, range:0-27899, partition values :[20200523]
20/06/25 12:19:39 ERROR Exception found
java.io.Exception:Not initated
    at.apache.java.org........
20/06/25 12:19:40 INFO executor.EXECUTOR: Finished task 18.0 in stage 0.0 (TID 18),18994 bytes result sent to driver.
20/06/25 12:20:41 WARN Warning as the node is accessed without started
 
LogType:stdout
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:

Container:container_e182_1234
=============================
LogType:container-localizer-syslog
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:
    
LogType:stderr
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:3000
Log Contents:
20/06/25 12:19:33 INFO datasources.FileScanRDD: Reading File path: hdfs://bpaiddev/dev/data/warehouse/clean/falcon/ukc/masked_data/parquet/FRAUD_CUSTOMER_INFORMATION/rcd_crt_dttm_yyyymmdd=20200523/part-0042-ed52abc2w.c000.snapp.parquet, range:0-27899, partition values :[20200523]
20/06/25 12:19:34 INFO executor.EXECUTOR: Finished task 18.0 in stage 0.0 (TID 18),18994 bytes result sent to driver.
     
LogType:stdout
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:

어떻게 해야 하나요? 이 문제를 해결하도록 도와주세요. 감사합니다!

답변1

다음 한 줄의 코드를 사용하여 sed동일한 결과를 얻을 수 있습니다(파일 이름이 이라고 가정 file).

sed -n 's/^.*LogType:\(stderr\)$/\1/p; s/^.*Log Upload Time :\(.*\)/\1/p; s/^.*LogLength:\(.*\)$/\1/p; s/^.*\(ERROR\|WARN\).*$/\0/p' file

그런 다음 리디렉션( >)을 사용하여 출력을 다른 파일에 저장할 수 있습니다.

더 쉽게 읽을 수 있도록 여러 줄로 나눕니다.

sed -n -e 's/^.*LogType:\(stderr\)$/\1/p' \
       -e 's/^.*Log Upload Time :\(.*\)/\1/p' \
       -e 's/^.*LogLength:\(.*\)$/\1/p' \
       -e 's/^.*\(ERROR\|WARN\).*$/\0/p' file

고쳐 쓰다

위의 솔루션은 OP에서 요청한 "LogType:stderr"의 일부가 아닌 청크를 제외하지 않습니다. 이는 sed단독 처리에 적합하지 않은 비로컬 정보(동일한 라인에 있지 않음)가 필요합니다.

다음 스크립트는 awk및 를 모두 사용합니다 sed(이 awk섹션은이 게시물), 다음 작업을 완료하세요.

#!/bin/bash
file=$1
awk '{
  if($0 ~ /LogType/){
    if(hold ~ /LogType:stderr/){
      print hold;
    }
    hold=$0
  }else{
    hold=hold "\n" $0
  }
}END{
  if(hold ~ /LogType:stderr/){
    print hold
  }
}' $file | sed -n -e 's/^.*LogType:\(stderr\)$/\1/p' \
                 -e 's/^.*Log Upload Time :\(.*\)/\1/p' \
                 -e 's/^.*LogLength:\(.*\)$/\1/p'       \
                 -e 's/^.*\(ERROR\|WARN\).*$/\0/p'

답변2

짧은 스크립트를 사용하여 할 수 있습니다. 원본 로그는 이 파일에 포함되어 있습니다 logdata.

#!/bin/bash

tmpfile="/tmp/$0.$$"

sed -n '/stderr/,/^ *$/p' logdata > "$tmpfile"
sed -n 's/^.*LogType:\(.*\)/\1/p
        s/^.*Log Upload Time :\(.*\)/\1/p
        s/^.*LogLength:\(.*\)/\1/p' "$tmpfile"
grep -E "(ERROR|WARN)" "$tmpfile"
rm "$tmpfile"

먼저 stderr청크를 임시 파일로 추출합니다. 그런 다음 두 필드를 제거한 다음 grep오류와 경고를 제거하십시오. 마지막 두 단계를 연결하려고 시도했지만 tee성공하지 못했습니다.

임시 파일 없이도 할 수 있어요

sed -n '/stderr/,/^ *$/p' logdata | \
sed -n 's/^.*LogType:\(.*\)/\1/p
        s/^.*Log Upload Time :\(.*\)/\1/p
        s/^.*LogLength:\(.*\)/\1/p
        /ERROR/p
        /WARN/p'

답변3

그리고 awk:

awk '
  /LogType:stderr/ || (p && /Log( Upload Time|Length)/){
    p=1                    # set flag for stderr block
    sub(/^[^:]+:/, "")     # replace content before `:` including `:`
    print                  # print (modified) line
  }
  p && / (WARN|ERROR) /{ 
    sub(/^[^0-9]*/, "")    # remove unknown prefix
    print
  }  
  /LogType:stdout/{ exit } # exit the script
' file

답변4

GNU sed확장된 정규식 패턴을 사용 하고 활용하세요.

sed -Ee '
  /LogType:stderr/,/^\s*$/!d
  /Log Contents:/,/^\s*$/!{
    s/^[^:]*://;b
  }
  /\s(ERROR|WARN)\s/!d
' logfile

설명하다:

  • 파일을 범위(로그 유형은 빈 줄)로 나눈 다음 각 범위를 (사전 로그 콘텐츠와 사후 로그 콘텐츠)로 세분화합니다.

  • 하위 범위 이전 블록에서 첫 번째 콜론 문자까지 삭제합니다. 그러나 하위 범위의 백 블록에 오류나 경고가 있는지 지금은 알 수 없으므로 아직 인쇄하지 마세요. 그래서 우리는 그것을 예약된 공간에 넣었습니다.

  • 하위 범위의 뒤쪽 블록에 도달하면 오류 또는 경고 라인이 감지됩니다. 그러면 보류가 즉시 검색되어 인쇄됩니다.

결과:

stderr
Thu Jun 25 12:24:52 +0100 2020
3000
20/06/25 12:19:39 ERROR Exception found
20/06/25 12:20:41 WARN Warning as the node is accessed without started

오류/경고 메시지의 줄 번호도 필요한 경우 위에서 수정한 다음 sed 명령을 사용합니다.

sed -Ee '
  /LogType:stderr/,/^\s*$/!d
  /Log Contents:/,/^\s*$/!{
    s/^[^:]*://;b
  }
  /\s(ERROR|WARN)\s/!d
  p;=;d
' logfile |
sed -Ee '/\s(ERROR|WARN)\s/N;s/\n/ on line #/'

또한 awk n perl과 같은 다른 도구를 사용하여 이를 수행할 수도 있습니다. 참고: 먼저 빈 줄의 후행 공백을 제거하십시오.

awk '
  BEGIN {
    RS = "\n\n"              
    FS = "\nLog Contents:\n" 
    OFS = "\n"               
    ORS = OFS                
    spc = "[[:blank:]]" 
    str = "(ERROR|WARN)" 
    pat = spc str spc 
  }
  /^LogType:stderr/ &&
  NF == 2 {
    p = $1; gsub(/(^|\n)[^:]+:/, "\n", p);sub(/./, "", p) 
    N = split($2, a, /\n/)
    print p
    for ( i=1; i<=N; i++ ) 
      if ( a[i] ~ pat ) 
        print a[i]
  }
' logfile
perl -F'/^Log\hContents:$/m,$_,2' -00 -ne '
  next if ! /\ALogType:stderr$/m;
  (my $pre = $F[0])=~ s/.*?://gm;
  my $post = join "\n",
    grep { /\s(?:ERROR|WARN)/ }
    split /\n/, $F[1];
  print($pre,$post);
' logfile

관련 정보