로그 파일이 있고 bash 스크립트를 통해 데이터를 "grep"하려고 합니다. 제가 특히 관심을 갖고 있는 데이터는 "ERR-" 패턴이 있고 가독성을 높이기 위해 각 항목 뒤에 빈 줄을 포함하는 두 타임스탬프(상위 타임스탬프 포함) 사이의 모든 행입니다.
예제 로그 파일:
Tue May 24 21:22:12 2022
ERR-0045 Lock detected in /tmp/file.lck
Tue May 24 21:44:12 2022
Errors in file /tmp/filename01.trc:
ERR-0001: Error detected. /tmp/filename.log
Tue May 24 21:47:25 2022
im some output
Tue May 24 21:47:25 2022
im some output too
im some output aswell
Tue May 24 21:48:03 2022
Errors in file /tmp/filename09.trc:
ERR-0100: error
ERR-0050: failure of sorts.
ERR-0052: line 3421
Tue May 24 21:49:07 2022
Completed process xyz
그래서 내가 원하는 출력은 다음과 같습니다.
Tue May 24 21:22:12 2022
ERR-0045 Lock detected in /tmp/file.lck
Tue May 24 21:44:12 2022
Errors in file /tmp/filename01.trc:
ERR-0001: Error detected. /tmp/filename.log
Tue May 24 21:48:03 2022
Errors in file /tmp/filename09.trc:
ERR-0100: error
ERR-0050: failure of sorts.
ERR-0052: line 3421
나는 큰 성공 없이 sed/awk/cat 조합을 사용해 보았습니다. 내가 문제가 있는 곳은 다음과 같습니다.
- ERR은 항상 타임스탬프 앞에 두 줄을 포함하지 않습니다.
- 타임스탬프 블록에는 여러 개의 ERR이 있을 수 있습니다.
- 날짜는 분명히 변경되므로 형식은 변경되지 않지만 하드코딩하고 싶지 않습니다.
미리 감사드립니다
답변1
스크립트 tst.awk
:
function print_r() { if (e) print r; r = ""; e = 0 }
/^([[:alpha:]]{3} ){2}[[:digit:]]{1,2} [[:digit:]]{2}(:[[:digit:]]{2}){2} [[:digit:]]{4}$/ {
print_r()
}
/^ERR-/{ e = 1 }
{ r = r ORS $0 }
END{ print_r() }
사용법 및 출력:
$ awk -f tst.awk file
Tue May 24 21:22:12 2022
ERR-0045 Lock detected in /tmp/file.lck
Tue May 24 21:44:12 2022
Errors in file /tmp/filename01.trc:
ERR-0001: Error detected. /tmp/filename.log
Tue May 24 21:48:03 2022
Errors in file /tmp/filename09.trc:
ERR-0100: error
ERR-0050: failure of sorts.
ERR-0052: line 3421
자신만의 표현식을 사용하여 타임스탬프나 오류를 나타낼 수 있습니다. 이는 제시된 형식과 일치하는 전체 행입니다(날짜 유효성 검사 없음). 줄 시작 부분에 "ERR-"를 추가하세요.
노트:
r
오류가 발견되면 레코드()를 인쇄하는 함수()를 정의합니다e
. 이 두 변수도 인쇄 후에 재설정해야 합니다. 의 경우awk
값으로 초기화되지 않은 변수는 빈 문자열 또는 0으로 평가됩니다.날짜에 대한 정규 표현식이 일치할 때 이 함수를 호출합니다. 이전 로깅을 완료하고 새 기록 저장을 시작합니다. 기록은 여러 줄의 로그이므로 인쇄해야 하는지 여부는 아직 알 수 없습니다.
오류 패턴이 일치하는 경우를 설정합니다
e
.각 행에 대해 기존 레코드에 행을 추가하고
ORS
출력 레코드 구분 기호(기본 줄 바꿈)로 구분합니다. 또한 출력 줄 사이의 빈 줄은 의 시작 부분에 배치됩니다r
.r
여기서 새 타임스탬프를 얻을 때 항상 빈 문자열이 됩니다.END
마지막 레코드가 아직 남아 있기 때문에 함수를 다시 호출합니다 .
답변2
사용행복하다(이전 Perl_6)
~$ raku -e 'my @a=slurp; @a.=split(/ <?after ^^ ERR \V* > \n <?before ^^ Tue > /); \
put $_.subst(/^ <(.+)> ^^ Tue/) ~ "\n" if /^^ ERR / for @a;' file
ERR
문제는 행이 있는 타임스탬프 레코드가 있고 행이 없는 레코드가 있고 후자를 삭제하려는 것 같습니다 .
위의 파일은 배열 slurp
로 구성 됩니다. @a
그런 다음 @a
시작하는 줄로 끝나는 레코드 사이에 split
0개 이상의 수직이 아닌 공백 문자가 오고, 다음으로 시작하는 줄 앞에 있습니다.\n
<?after ^^ ERR \V* >
ERR
\V
<?before ^^ Tue >
Tue
두 번째 문에서는 out이 put(…)
세련됩니다. 이러한 요소는 조항의 전문에 @a
개별적으로(자동으로) 표시됩니다 . 각 요소는 조건부로 테스트되어 :으로 시작하는 줄이 포함되어 있는지 확인합니다. 따라서 요소가 대체되고 이전의 모든 선행 문자가 제거됩니다.$_
for
if /^^ ERR/
ERR
if
$_
$_.subst(/^ <(.+)> ^^ Tue/)
내부Tue
본질적으로 .subst
여기서 교체가 없다는 것은 캡처 태그 사이의 일치 항목을 제거한다는 의미 입니다 <(
. )>
개별 레코드를 구분하기 위해 $_.subst(…) ~ "\n"
요소는 ~
물결표와 레코드를 구분하는 개행 문자로 "\n"
연결됩니다 .
입력 예:
Tue May 24 21:22:12 2022
ERR-0045 Lock detected in /tmp/file.lck
Tue May 24 21:44:12 2022
Errors in file /tmp/filename01.trc:
ERR-0001: Error detected. /tmp/filename.log
Tue May 24 21:47:25 2022
im some output
Tue May 24 21:47:25 2022
im some output too
im some output aswell
Tue May 24 21:48:03 2022
Errors in file /tmp/filename09.trc:
ERR-0100: error
ERR-0050: failure of sorts.
ERR-0052: line 3421
Tue May 24 21:49:07 2022
Completed process xyz
예제 출력:
Tue May 24 21:22:12 2022
ERR-0045 Lock detected in /tmp/file.lck
Tue May 24 21:44:12 2022
Errors in file /tmp/filename01.trc:
ERR-0001: Error detected. /tmp/filename.log
Tue May 24 21:48:03 2022
Errors in file /tmp/filename09.trc:
ERR-0100: error
ERR-0050: failure of sorts.
ERR-0052: line 3421
물론 위의 내용은 간단한 구현입니다(가독성을 높이기 위한 것입니다). 다른 요일에 시작하는 날짜를 처리하려면 Tues
위의 내용을 다음으로 바꾸세요.
[ Mon || Tue || Wed || Thu || Fri || Sat || Sun ]
(구체성에 문제가 있는 경우 정규식에 월을 추가하는 방법을 위의 코드에서 명확하게 알 수 있습니다.)