아래와 같은 로그가 포함된 대용량 파일이 있습니다. 대략 30,000건의 그러한 사건이 기록되었습니다. RINGING
and CLOSE
(includes)로 시작하고 를 포함하지 않는 줄을 추출해야 합니다 30 30
.
요구사항은 다음과 같습니다.
아래에 표시된 두 인스턴스 중 인스턴스 2만 유지하면 됩니다. 인스턴스 1을 완전히 제거해야 합니다(파일의 대부분을 차지함).
예시 1:
313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data
313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93
313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8
313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00 ...
313787 Aug 19 18:37:19.485: <DATA> OUT |254|01136097645|5950|$hostIp|133 bytes |30 30 60 00 00 00 06 6F 12 10 ...
313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data
예 2:
(30 30이 있는 행은 존재하지 않습니다)
313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data
313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93
313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8
313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00 ...
313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data
답변1
로그 파일 이름이 이라고 가정하면 샘플 출력이 포함된 솔루션 logfile
은 다음과 같습니다 .awk
$ awk '/RINGING/,/CLOSE/ {if (/30 30/){f=1}; a=a"\n"$0} f==0 && /CLOSE/ {print a} /CLOSE/{a="";f=0}' logfile
313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data
313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93
313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8
313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00
313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data
설명하다
awk
각 명령을 순서대로 실행합니다.
/RINGING/,/CLOSE/ {if (/30 30/){f=1}; a=a"\n"$0}
표현식
/RINGING/,/CLOSE/
은 범위입니다. 명령이 행 그룹에만 적용되도록 지정합니다. 그룹은 텍스트가 포함된 줄을 만나면 시작됩니다RINGING
.CLOSE
텍스트가 포함된 줄을 만나면 그룹 이 종료됩니다. 이러한 그룹의 모든 행에 대해 중괄호로 묶인 명령이 실행됩니다.f
첫 번째는 행에 가 포함되어 있으면 플래그를 1로 설정합니다30 30
. 두 번째 명령은 현재 행을 변수에 추가합니다a
.f==0 && /CLOSE/ {print a}
여기서 중괄호 안의 명령 앞에는 두 가지 조건이 함께 연결되어 있습니다. 첫 번째 조건은 플래그가
f
0(30 30
그룹에서 찾을 수 없음)임을 지정하고 두 번째 조건은 행에 text 가 포함되어 있음을 지정합니다CLOSE
. 두 조건이 모두 충족되면a
변수에 저장된 행 그룹을 인쇄합니다./CLOSE/{a="";f=0}
마지막으로 text 가 포함된 줄에서
CLOSE
변수는a
빈 문자열로 재설정되고 플래그는f
0으로 설정됩니다. 이 작업이 완료되면 코드는 다음 줄 세트(있는 경우)에서 시작할 준비가 됩니다.
답변2
예를 들어 Perl 호환 정규식(PCRE)을 사용할 수 있습니다.
pcregrep -M '^.*?RINGING(?(?!30 30)(?s).)+?CLOSE.*?$' file
또는
grep -zPo '^.*?RINGING(?(?!30 30)(?s).)+?CLOSE.*?$' file
또는 GNU awk의 보다 표현력이 뛰어난 레코드 구분 기호를 사용하세요.
gawk -vRS="CLOSE[^\n]*\n" -vORS= '!/30 30/ {print; print RT}' file