내 서버에 거대한 로그 파일(수십 GB)이 있습니다. 적당한 시간에 다운로드하기에는 용량이 너무 큽니다. 그러나 나는 상대적으로 작은 선의 하위 집합에만 관심이 있습니다. 로그 파일은 XML과 유사한 구조를 가지고 있습니다. 많은 항목이 있고 <log>...</log>
그중 하나에 내가 찾고 있는 특정 패턴이 있습니다. 예를 들어 "Failure"
(일치 항목이 1개만 있는 경우 grep
) "Failure"
:
<log>...</log>
<log>...</log>
....
<log> (*1*)
...
... "Failure" ...
...
</log> (*2*)
....
<log>...</log>
<log>...</log>
내 생각은 이전 및 다음 항목과 포함된 줄의 이전 및 이후 위치를 별도로 검색하는 것입니다 <log>
(*1*)
. 나중에 이 줄을 별도의 파일로 복사하여 쉽게 다운로드할 수 있도록 하고 싶습니다.</log>
(*2*)
"Failure"
의사코드 요약:
failure_line = find pattern "Failure" in log file
start_line = find immediate previous occurrence of <log> before the line failure_line
finish_line = find immediate next occurrence of </log> after the line failure_line
copy all lines from start_line until finish_line to a new file
bash
많은 오버헤드 없이 스크립트를 통해 이를 달성할 수 있습니까 ?
답변1
sed
, perl
또는 같은 표준 텍스트 처리 도구는 awk
XML 구문 분석에 사용되지 않습니다. <log>...</log>
연속으로 두 개 이상의 쌍을 갖지 않는 등의 방법을 사용할 수 있다면 다음과 같이 할 수 있습니다 sed
.
sed '/<log>.*<\/log>/{/Failure/p;d;};/<log>/,/<\/log>/H;/<log>/h;/<\/log>/!d;x;/Failure/!d' your.log
- '/.*</log>/'는 완전한 태그가 있는 행과 일치합니다. 이러한 항목은 별도로 처리해야 합니다.
/Failure/p
포함된 경우 인쇄하고Failure
추가d
처리를 중지합니다. - 이제 시작과 끝 사이의 줄을
/<log>/,/<\/log>/
선택 하고 예약된 공간의 클립보드에 추가합니다( ).<log>
</log>
sed
H
/<log>/h
log
새로운 시퀀스에 대해 예약된 공간을 초기화합니다./<\/log>/!d
닫히는 행을 제외한 모든 행 처리를 중지합니다.</log>
- 따라서 로그를 닫을 때 다음을 수행하십시오.
x
보류 공간과 패턴 공간을 교환하면 이전 줄 이후 패턴 공간의 모든 항목이 수집됩니다<log>
.d
포함되지 않은 경우 제거하십시오Failure
. 그렇지 않으면 기본적으로 스크립트 끝에 인쇄됩니다.