它在做什么

它在做什么

输入文件

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

您将需要多次通行证。这是一个使用sedsortheadcut按您想要的顺序给出前 5 个的解决方案。

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/'

这是相当拗口的,但它是必要的,以避免灾难性的回溯

我们正在使用正则表达式替换。要详细了解它在做什么,尝试正则表达式101。现在,知道它需要输入:

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按升序排序,将最大值放在最后。因为这意味着处理全部ofsort的输出找到最大的 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 个值。所以我们使用heads-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: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

相关内容