그게 뭐하는거야?

그게 뭐하는거야?

입력 파일

Mar 19 06:10:16 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:00:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
Mar 19 14:41:26 ip-172-2-0-53 sendmail[29483]: v2JLfNFN029481: to=<[email protected]>,<[email protected]>, delay=00:00:03, xdelay=00:00:03, mailer=esmtp, pri=151738, relay=ifaded-com.mail.p...ction.outlook.com. [xx.xxx.x.x], dsn=2.0.0, stat=Sent (<[email protected]> [InternalId=31288836753166, Hostname=ERGsDGddssdD5.namprd07.prod.outlook.com] 8924 bytes in 0.309, 28.142 KB/sec Queued mail for delivery)
Mar 19 06:10:26 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:20:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)

나는 다음 명령을 시도했습니다

 cat logh.txt | grep -E -o " delay=.[^,]*|^[^ip]+" 

나는 날짜와 함께 상위 5개 지연 시간을 알고 싶습니다. llinux 명령으로 이 문제를 어떻게 해결할 수 있습니까? 나는 다음과 같은 결과를 얻고 있습니다

Mar 19 06:10:16
 delay=00:00:15
Mar 19 14:41:26
 delay=00:00:03
Mar 19 06:10:26
 delay=00:20:15

원하는 출력

  Mar 19 06:10:26 delay=00:20:15
  Mar 19 06:10:16 delay=00:00:15
  Mar 19 14:41:26 delay=00:00:03

답변1

여러 번의 패스가 필요합니다. 다음은 sed, 및 를 sort사용 하여 원하는 순서대로 상위 5개를 제공하는 솔루션입니다 .headcut

sed -e 's/^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*/\4\5\6 \1 \3/' | sort -nr | head -n5 | cut -d\  -f2-

제공된 입력을 사용하면 다음이 방출됩니다.

Mar 19 06:10:26 delay=00:20:15
Mar 19 06:10:16 delay=00:00:15
Mar 19 14:41:26 delay=00:00:03

(입력이 제공한 로그 형식이고 원하는 데이터가 있는 행만 제공된다고 가정합니다. 처음에 추가 grep이 필요할 수 있습니다.)

그게 뭐하는거야?

그것을 분석해 봅시다.

sed

sed스트림 편집자를 나타냅니다. 텍스트 스트림에 정규식을 적용하는 데 일상적으로 사용됩니다.

sed의 정규 표현식

's/^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*/\4\5\6 \1 \3/'

꽤 많은 내용이지만, 피하려면 그럴 필요가 있습니다.치명적인 역추적.

우리는 정규식 대체를 사용하고 있습니다. 무슨 일을 하는지 자세히 보려면,Regex101을 사용해보십시오. 지금은 입력이 필요하다는 것을 알고 있습니다.

Mar 19 06:10:16 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:00:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
Mar 19 14:41:26 ip-172-2-0-53 sendmail[29483]: v2JLfNFN029481: to=<[email protected]>,<[email protected]>, delay=00:00:03, xdelay=00:00:03, mailer=esmtp, pri=151738, relay=ifaded-com.mail.p...ction.outlook.com. [xx.xxx.x.x], dsn=2.0.0, stat=Sent (<[email protected]> [InternalId=31288836753166, Hostname=FOOBAR1.namprd07.prod.outlook.com] 8924 bytes in 0.309, 28.142 KB/sec Queued mail for delivery)
Mar 19 06:10:26 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:20:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)

그리고 그것을 다음으로 변환합니다.

000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03
002015 Mar 19 06:10:26 delay=00:20:15

sed 정규식 일치

^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*

먼저 날짜 구성 요소를 명시적으로 일치시킵니다. 나중에 출력을 위해 그것들이 필요할 것입니다. 그런 다음 지연과 타이밍 구성 요소를 개별적으로 찾아서 일치시킵니다. 지연은 출력에서 ​​원했습니다. 나중에 정렬을 위해 필요한 타이밍 구성요소입니다.

sed의 정규식 대체

\4\5\6 \1 \3

정규식의 대체 측면에서는 우리가 파악한 타이밍 구성 요소를 가져와서 원래 있던 ":" 구분 기호 없이 연결합니다. 이는 나중에 사용할 것이므로 중요합니다 sort. 타이밍 구성 요소 뒤에 날짜 문자열과 전체 원래 지연 문자열을 추가합니다. 우리는 정렬 후에 그것들을 원할 것입니다.

종류

sort -nr

이제 입력이 문자열 타임스탬프 대신 십진수로 시작되므로 플래그 sort로 지정된 의 숫자 모드를 사용할 수 있습니다 -n.

기본적으로 sort오름차순으로 정렬되어 가장 큰 값이 끝에 배치됩니다. 이는 처리를 의미하므로모두sort출력에서 ​​가장 큰 N 값을 찾으려면 sort의 -r플래그를 사용하여 출력 순서를 바꿉니다. 이제 가장 큰 값이 먼저 출력되며 head'tail' 대신에 할 수 있습니다.

이 시점의 출력은 다음과 같습니다.

002015 Mar 19 06:10:26 delay=00:20:15
000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03

머리

head -n5

이 시점에서 입력은 가장 큰 값을 먼저 갖게 되며 가장 큰 5개의 값을 원한다는 것을 이미 알고 있습니다. 그래서 우리 head는 의 매개변수를 사용하여 우리가 원하는 값의 수를 -n알려줍니다 .head

이 예에서는 실제로 5개 이상의 값이 없으므로 입력된 모든 출력을 여전히 얻습니다.

002015 Mar 19 06:10:26 delay=00:20:15
000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03

자르다

cut -d\  -f2-

더 이상 필요하지 않으므로 sed첫 번째 단계에서 삽입한 숫자 정렬 키를 제거해야 합니다. 이를 위해 cut제공된 각 행에서 원하는 필드를 선택할 수 있도록 합니다.

컷의 -d매개변수를 사용하여 필드 구분 기호, 구분 기호가 무엇인지 알려줍니다. 필드 구분 기호는 공백이므로 로 이스케이프 처리하여 를 제공해야 \합니다 -d\.

cut의 관점 에서 볼 때 이는 행 002015 Mar 19 06:10:26 delay=00:20:15002015 Mar 19 06:10:26 delay=00:20:15.

원하는 필드를 지정하기 위해 를 사용합니다 -f. 첫 번째 필드를 제외한 모든 필드를 원하므로 를 사용하여 -f2-원하는 출력을 제공합니다.

Mar 19 06:10:26 delay=00:20:15
Mar 19 06:10:16 delay=00:00:15
Mar 19 14:41:26 delay=00:00:03

답변2

perl -lane '
   print join $", /\sdelay=\K(\S+)(?=,)/, splice(@F, 0, 3), /\s\K(delay=\S+)(?=,)/;
' | sort -t: -k 1,1nr -k 2,2nr -k 3,3nr | cut -d\  -f2- | head -n 5

관련 정보