입력 파일
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개를 제공하는 솔루션입니다 .head
cut
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:15
을 002015
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