이전에 다른 일치 패턴 전후에 패턴이 나타나는 것을 검색하고 그 사이의 모든 것을 별도의 파일로 추출합니다.

이전에 다른 일치 패턴 전후에 패턴이 나타나는 것을 검색하고 그 사이의 모든 것을 별도의 파일로 추출합니다.

내 서버에 거대한 로그 파일(수십 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또는 같은 표준 텍스트 처리 도구는 awkXML 구문 분석에 사용되지 않습니다. <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>sedH
  • /<log>/hlog새로운 시퀀스에 대해 예약된 공간을 초기화합니다.
  • /<\/log>/!d닫히는 행을 제외한 모든 행 처리를 중지합니다.</log>
  • 따라서 로그를 닫을 때 다음을 수행하십시오. x보류 공간과 패턴 공간을 교환하면 이전 줄 이후 패턴 공간의 모든 항목이 수집됩니다 <log>. d포함되지 않은 경우 제거하십시오 Failure. 그렇지 않으면 기본적으로 스크립트 끝에 인쇄됩니다.

관련 정보