AWK는 두 패턴 사이의 줄을 인쇄합니다. 일치하는 줄의 마지막 항목만 인쇄하면 됩니다.

AWK는 두 패턴 사이의 줄을 인쇄합니다. 일치하는 줄의 마지막 항목만 인쇄하면 됩니다.

로그 파일을 필터링하고 두 일치 항목 사이에 몇 줄을 인쇄하고 마지막 일치 항목만 인쇄하고 싶습니다.

샘플 파일 내용:

2023-03-08 11:12:44,306 - Code Deploy - INFO - Received signal
2023-03-08 11:12:44,306 - Code Deploy - INFO - Received message signal
2023-03-08 11:12:44,306 - Code Deploy - INFO - Branch is Testing
2023-03-08 11:12:44,307 - Code Deploy - INFO - Deployment started
2023-03-08 11:13:31,782 - Code Deploy - INFO - Old version2_0_5_12
2023-03-08 11:13:31,783 - Code Deploy - INFO - New version2_0_5_13
2023-03-08 11:13:32,553 - Code Deploy - INFO - Permission fixed
2023-03-08 11:13:32,554 - Code Deploy - INFO - Deployment finished
2023-03-08 11:13:34,900 - Code Deploy - ERROR - !!!!!!!!!! EXCEPTION !!!!!!!!!(535, b'5.7.8     Username and Password not accepted. Learn more at\n5.7.8  https://support.google.com/mail/?p=BadCredentials z16-20020a170903019000b0019a97a4324dsm9818181plg.5 - gsmtp')Traceback (most recent call last):
File "/root/code-dployment/server/deploy.py", line 94, in send_email
server.login(gmail_user, gmail_password)
File "/usr/lib/python3.5/smtplib.py", line 729, in login
raise last_exception
File "/usr/lib/python3.5/smtplib.py", line 720, in login
initial_response_ok=initial_response_ok)
File "/usr/lib/python3.5/smtplib.py", line 641, in auth
raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8  https://support.google.com/mail/?p=BadCredentials z16-20020a170903019000b0019a97a4324dsm9818181plg.5 - gsmtp')

2023-03-09 11:52:57,194 - Code Deploy - INFO - Received signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received message signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Branch is Testing
2023-03-09 11:52:57,195 - Code Deploy - INFO - Deployment started
2023-03-09 11:53:58,246 - Code Deploy - INFO - Old version2_0_5_13
2023-03-09 11:53:58,246 - Code Deploy - INFO - New version2_0_5_14
2023-03-09 11:53:58,498 - Code Deploy - INFO - Permission fixed
2023-03-09 11:53:58,498 - Code Deploy - INFO - Deployment finished
2023-03-09 11:54:00,797 - Code Deploy - ERROR - !!!!!!!!!! EXCEPTION !!!!!!!!!(535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8  https://support.google.com/mail/?p=BadCredentials k17-20020aa790d1000000b005907716bf8bsm11097506pfk.60 - gsmtp')Traceback (most recent call last):
File "/root/code-dployment/server/deploy.py", line 94, in send_email
server.login(gmail_user, gmail_password)
File "/usr/lib/python3.5/smtplib.py", line 729, in login
raise last_exception
File "/usr/lib/python3.5/smtplib.py", line 720, in login
initial_response_ok=initial_response_ok)
File "/usr/lib/python3.5/smtplib.py", line 641, in auth
raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8  https://support.google.com/mail/?p=BadCredentials k17-20020aa790d1000000b005907716bf8bsm11097506pfk.60 - gsmtp')

두 스키마 사이의 콘텐츠를 가져와야 합니다.

Pattern1 = '신호 수신'

Pattern2 = '배포 완료'

예상되는 결과:

2023-03-09 11:52:57,194 - Code Deploy - INFO - Received signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received message signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Branch is Testing
2023-03-09 11:52:57,195 - Code Deploy - INFO - Deployment started
2023-03-09 11:53:58,246 - Code Deploy - INFO - Old version2_0_5_13
2023-03-09 11:53:58,246 - Code Deploy - INFO - New version2_0_5_14
2023-03-09 11:53:58,498 - Code Deploy - INFO - Permission fixed
2023-03-09 11:53:58,498 - Code Deploy - INFO - Deployment finished

bash 스크립트에서 AWK 명령을 사용하고 싶습니다. 다음 명령을 사용하여 두 모드 간에 콘텐츠를 필터링하는 솔루션을 찾았습니다.

# awk '/Received signal/,/Deployment finished/' /tmp/result.log

전체 일치하는 행의 모든 ​​항목을 인쇄하지만 일치하는 패턴의 마지막 항목만 인쇄하도록 필터링해야 합니다.

위 명령의 출력은 다음과 같습니다.

2023-03-08 11:12:44,306 - Code Deploy - INFO - Received signal
2023-03-08 11:12:44,306 - Code Deploy - INFO - Received message signal
2023-03-08 11:12:44,306 - Code Deploy - INFO - Branch is Testing
2023-03-08 11:12:44,307 - Code Deploy - INFO - Deployment started
2023-03-08 11:13:31,782 - Code Deploy - INFO - Old version2_0_5_12
2023-03-08 11:13:31,783 - Code Deploy - INFO - New version2_0_5_13
2023-03-08 11:13:32,553 - Code Deploy - INFO - Permission fixed
2023-03-08 11:13:32,554 - Code Deploy - INFO - Deployment finished
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received message signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Branch is Testing
2023-03-09 11:52:57,195 - Code Deploy - INFO - Deployment started
2023-03-09 11:53:58,246 - Code Deploy - INFO - Old version2_0_5_13
2023-03-09 11:53:58,246 - Code Deploy - INFO - New version2_0_5_14
2023-03-09 11:53:58,498 - Code Deploy - INFO - Permission fixed
2023-03-09 11:53:58,498 - Code Deploy - INFO - Deployment finished

답변1

awk를 사용하고 다음 스크립트 중 하나와 매우 유사합니다.@terdon의 답변하지만 제 생각에는 awk의 condition { action }기본 구조를 사용하는 것이 좀 더 관용적입니다.

$ awk '
    /Received signal/ { f=1; rec="" }
    f { rec = rec $0 ORS }
    /Deployment finished/ { f=0 }
    END { if (f=="0") printf "%s", rec }
' file
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received message signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Branch is Testing
2023-03-09 11:52:57,195 - Code Deploy - INFO - Deployment started
2023-03-09 11:53:58,246 - Code Deploy - INFO - Old version2_0_5_13
2023-03-09 11:53:58,246 - Code Deploy - INFO - New version2_0_5_14
2023-03-09 11:53:58,498 - Code Deploy - INFO - Permission fixed
2023-03-09 11:53:58,498 - Code Deploy - INFO - Deployment finished

이것과 @terdon의 답변 사이의 약간의 기능적 차이점은 다음과 같습니다.

  1. RS='\r\n'ORS를 RS와 다른 값으로 설정하기로 결정한 경우(예: 로 변환하려는 경우 ORS='\n') 필요한 레코드 종결자가 생성되고 @terdon은 ORS를 사용하여 대부분의 출력 끝에서 RS 값을 재현합니다.
  2. 입력 파일에 줄이 없으면 @terdon은 빈 줄을 인쇄 Received signal하고 파일은 출력을 생성하지 않습니다.
  3. 입력에 두 개의 구분 기호가 있는 경우 이 명령은 구분 기호 사이의 텍스트만 인쇄하는 반면, @terdon은 후속 줄이 Received signal없더라도 줄 뒤의 모든 항목을 인쇄합니다 Deployment finished.

귀하의 질문 과 관련하여 awk '/Received signal/,/Deployment finished/' /tmp/result.log- 범위 표현식을 사용하지 말고 플래그를 사용하십시오.awk에서 시작 끝 범위 표현이 항상 유용함. 범위 표현식을 사용하는 지금까지 게시된 모든 답변에서 볼 수 있듯이 동일한 조건에 대해 두 가지 테스트가 필요합니다.

답변2

파일을 반전시켜 범위에 없는 모든 줄을 제거 /Deployment finished/,/Received signal/하고 줄 범위의 끝이 일치하는 즉시 종료합니다. 그런 다음 결과를 반전시킵니다.

tail -r file |
sed -e '/Deployment finished/,/Received signal/!d' -e '/Received signal/q' |
tail -r

GNU 시스템 사용자는 위의 방법 tac대신 이것을 사용할 수 있습니다 .tail -r

사용해야 한다고 생각되면 awksed파이프라인의 명령을 다음으로 바꾸세요.

awk '/Deployment finished/,/Received signal/; /Received signal/ { exit }'

문제의 데이터를 제공하는 출력:

2023-03-09 11:52:57,194 - Code Deploy - INFO - Received signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received message signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Branch is Testing
2023-03-09 11:52:57,195 - Code Deploy - INFO - Deployment started
2023-03-09 11:53:58,246 - Code Deploy - INFO - Old version2_0_5_13
2023-03-09 11:53:58,246 - Code Deploy - INFO - New version2_0_5_14
2023-03-09 11:53:58,498 - Code Deploy - INFO - Permission fixed
2023-03-09 11:53:58,498 - Code Deploy - INFO - Deployment finished

답변3

간단한 방법은 각 일치 항목을 변수에 저장하고 이전 내용을 덮어쓴 다음 스크립트 끝에 변수를 인쇄하는 것입니다.

$ awk '{ 
         if(/Received signal/){k=1; v=$0} 
         else if(k==1){
           v=v RS $0; 
           if(/Deployment finished/){ k=0 }
         }
       } 
       END{ print v }' result.log
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received message signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Branch is Testing
2023-03-09 11:52:57,195 - Code Deploy - INFO - Deployment started
2023-03-09 11:53:58,246 - Code Deploy - INFO - Old version2_0_5_13
2023-03-09 11:53:58,246 - Code Deploy - INFO - New version2_0_5_14
2023-03-09 11:53:58,498 - Code Deploy - INFO - Permission fixed
2023-03-09 11:53:58,498 - Code Deploy - INFO - Deployment finished

또는 tac파일을 뒤집은 다음 첫 번째 일치 항목을 인쇄할 수 있습니다.

$ tac result.log | 
   awk '/Deployment finished/,/Received signal/{
      print; 
      if(/Received signal/){ exit }
   }' | tac
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received message signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Branch is Testing
2023-03-09 11:52:57,195 - Code Deploy - INFO - Deployment started
2023-03-09 11:53:58,246 - Code Deploy - INFO - Old version2_0_5_13
2023-03-09 11:53:58,246 - Code Deploy - INFO - New version2_0_5_14
2023-03-09 11:53:58,498 - Code Deploy - INFO - Permission fixed
2023-03-09 11:53:58,498 - Code Deploy - INFO - Deployment finished

답변4

사용행복하다(이전 Perl_6)

~$ raku -e 'my $k; my @v; for lines() { 
            if /Received \s signal/ {$k = 1; @v = $_} 
            elsif ($k == 1) { @v.push: $_ }; 
            if /Deployment \s finished/ {$k = 0}
            }; .put for @v;'  file
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Received message signal
2023-03-09 11:52:57,194 - Code Deploy - INFO - Branch is Testing
2023-03-09 11:52:57,195 - Code Deploy - INFO - Deployment started
2023-03-09 11:53:58,246 - Code Deploy - INFO - Old version2_0_5_13
2023-03-09 11:53:58,246 - Code Deploy - INFO - New version2_0_5_14
2023-03-09 11:53:58,498 - Code Deploy - INFO - Permission fixed
2023-03-09 11:53:58,498 - Code Deploy - INFO - Deployment finished

위의 코드는 @terdon의 훌륭한 awk코드를 뻔뻔하게 따르지만 Raku로 다시 작성되었습니다. @terdon이 지적한 핵심은 공개 정규식이 발견될 @v때마다 "저장 변수"(이 경우 배열)를 덮어쓰는 것입니다. /Received \s signal/여기서는 lines모두 토픽 변수에 하나씩 로드되기 때문에 $_코드를 사용합니다.@v = $_

/Deployment \s finished/파일의 끝에 도달했을 때 끝이 보일 때까지 아무것도 반환되지 않도록 하려면 (예: "전체 기록" 요구 사항) 최종 출력 put문을 다음과 같이 변경하세요.

.put if $k == 0 for @v;

#OR

.put unless $k == 1 for @v;

https://docs.raku.org/언어/control.html#Control_flow
https://raku.org

관련 정보