Você precisará de vários passes. Aqui está uma solução que usa sed
, sort
, head
e cut
para dar a você o top 5 na ordem desejada.
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\}\)\).*/ /' | sort -nr | head -n5 | cut -d\ -f2-
Com sua entrada fornecida, isso é emitido:
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
(Presume-se que sua entrada esteja no formato de log que você forneceu, e que seja apenas linhas alimentadas com os dados que você deseja. Um grep adicional no início pode ser necessário.)
O que está fazendo
Vamos dividi-lo.
sed
sed
significa o Stream EDitor. É usado rotineiramente para aplicar expressões regulares a fluxos de texto.
expressão regular de 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\}\)\).*/ /'
Isso é muito bom, mas precisa ser, para evitar retrocesso catastrófico .
Estamos usando as substituições do Regex. Para ver o que está fazendo em detalhes, experimente o Regex101 . Por enquanto, saiba que é necessária a entrada:
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)
e converte para
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
correspondência regex 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\}\)\).*
Primeiramente, combinamos explicitamente os componentes de data; vamos precisar disso para a saída, depois. Nós então encontramos e combinamos o atraso e seus componentes de temporização individualmente; o atraso, você queria na sua saída. Os componentes de tempo, nós precisaremos depois, para ordenar.
substituição de regex de sed
No lado de substituição do regex, pegamos os componentes de tempo que pegamos, e os concatenamos sem o delimitador ":" que eles originalmente tinham. Isso é importante, já que vamos usá-los para sort
depois. Após os componentes de temporização, anexamos a string date e toda a string de delay original; nós os queremos depois que classificarmos.
classificar
sort -nr
Como nossa entrada agora começa com um número decimal em vez de um registro de data e hora, podemos usar o modo numérico de sort
, especificado com o sinalizador -n
.
Por padrão, sort
classifica em ordem crescente, o que coloca os maiores valores no final. Como isso significaria processar all da saída de sort
para encontrar os maiores N valores, usamos o sinalizador -r
da classificação para reverter a ordem de saída; Agora, os maiores valores serão exibidos primeiro e podemos usar head
em vez de "tail".
Nossa saída, neste ponto, é assim:
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
cabeça
head -n5
Neste ponto, nossa entrada terá os maiores valores primeiro e já sabemos que queremos os 5 maiores valores. Portanto, usamos o parâmetro head
de -n
para informar a head
quantos valores desejamos.
Como neste exemplo não temos mais de 5 valores, ainda obtemos toda a saída em que fomos alimentados.
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
corte
cut -d\ -f2-
Como não precisamos mais dela, precisamos remover a chave numérica de classificação inserida com sed
no primeiro passo. Para isso, recorremos a cut
, o que nos permite escolher quais campos queremos de cada linha fornecida.
Usamos o parâmetro -d
do cut para dizer qual é o nosso separador de campo, nosso delimitador. Como o separador de campos é o espaço em branco, precisamos escapar com \
, o que nos dá -d\
.
Da perspectiva de cut
, isso divide a linha 002015 Mar 19 06:10:26 delay=00:20:15
em 002015
Mar
19
06:10:26
delay=00:20:15
.
Para especificar quais campos desejamos, usamos -f
. Como queremos todos, exceto o primeiro campo, usamos -f2-
, o que nos dá a saída desejada:
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