Входной файл
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
означает 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