Что он делает?

Что он делает?

Входной файл

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означает Stream EDitor. Он обычно используется для применения регулярных выражений к текстовым потокам.

регулярное выражение 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/'

Это довольно сложно, но так и должно быть, чтобы избежатькатастрофический откат назад.

Мы используем замены Regex. Чтобы увидеть, что это делает в деталях,попробуйте 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, что позволяет нам выбирать, какие поля мы хотим получить из каждой предоставленной строки.

Мы используем параметр 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

Связанный контент