규칙과 일치하는 특정 컬렉션 행 추출

규칙과 일치하는 특정 컬렉션 행 추출

아래와 같은 로그가 포함된 대용량 파일이 있습니다. 대략 30,000건의 그러한 사건이 기록되었습니다. RINGINGand 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}

    여기서 중괄호 안의 명령 앞에는 두 가지 조건이 함께 연결되어 있습니다. 첫 번째 조건은 플래그가 f0( 30 30그룹에서 찾을 수 없음)임을 지정하고 두 번째 조건은 행에 text 가 포함되어 있음을 지정합니다 CLOSE. 두 조건이 모두 충족되면 a변수에 저장된 행 그룹을 인쇄합니다.

  • /CLOSE/{a="";f=0}

    마지막으로 text 가 포함된 줄에서 CLOSE변수는 a빈 문자열로 재설정되고 플래그는 f0으로 설정됩니다. 이 작업이 완료되면 코드는 다음 줄 세트(있는 경우)에서 시작할 준비가 됩니다.

답변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

관련 정보