如果在 sed 中找到匹配项,则跳过两行

如果在 sed 中找到匹配项,则跳过两行

我正在尝试使用 清理文本文件sed

我有一个运行 ping 并输出到文本文件的程序。在程序中,我在 ping 输出后添加了一个时间戳,以便我知道它何时失败。

我需要删除除 ping 失败以及下面两行和上面一行之外的所有内容。如果sed满足我的表达,有什么办法可以跳过接下来的两行吗?

例子:

--- 8.8.8.8 ping statistics ---
rtt min/avg/max/mdev = 18.001/21.159/26.006/2.959 ms
Tue 26 Nov 09:39:56 GMT 2019


--- 4.2.2.2 ping statistics ---
10 packets transmitted, 9 received, 10% packet loss, time 18034ms
rtt min/avg/max/mdev = 20.560/34.013/70.076/17.428 ms
Tue 26 Nov 09:40:46 GMT 2019

--- 8.8.8.8 ping statistics ---
rtt min/avg/max/mdev = 17.510/20.543/26.618/2.317 ms
Tue 26 Nov 09:41:04 GMT 2019

如果我使用以下内容: sed '/loss/!d' pingFailed.txt > pingFailed1.txt

然后我的输出看起来像这样:

10 packets transmitted, 4 received, 60% packet loss, time 18103ms
10 packets transmitted, 3 received, 70% packet loss, time 18107ms

但我需要我的输出看起来像这样:

--- 4.2.2.2 ping statistics ---
10 packets transmitted, 9 received, 10% packet loss, time 18034ms
rtt min/avg/max/mdev = 20.560/34.013/70.076/17.428 ms
Tue 26 Nov 09:40:46 GMT 2019

我怎样才能做到这一点(最好是在sed)?

答案1

告诉我这是否适合您:

grep -B1 -A2 "loss" pingFailed.txt > pingFailed1.txt

输出:

--- 4.2.2.2 ping statistics ---
10 packets transmitted, 9 received, 10% packet loss, time 18034ms
rtt min/avg/max/mdev = 20.560/34.013/70.076/17.428 ms
Tue 26 Nov 09:40:46 GMT 2019

找到模式为“loss”的行:

grep "loss"

打印一行之前:

-B1

打印两行A之后:

-A2

答案2

要做到这一点sed

sed -n '/loss/ { x; G; N; N; p; s/.*// }; x' pingFailed.txt > pingFailed1.txt

解释:

  • -n:不自动打印任何内容;仅当存在时才打印p打印命令。
  • /loss/ { … }:当看到包含“ ”的行时执行大括号内的命令loss
  • x:交换模式空间和保持空间。模式空间包含我们刚刚读取的行。剧透警告:保留空间包含上一行。执行此命令后,模式空间包含前一行,保留空间包含当前行。
  • G:获取保留空间的内容并将其附加到模式空间(在它们之间插入换行符)。在该命令之后,模式空间包含前一行和当前行(即,该loss行及其之前的行)。
  • N:从输入中读取另一行并将其附加到模式空间(在它们之间插入换行符)。
  • p:打印模式空间,此时,模式空间包含该 loss行、其前一行和其后两行。
  • s/.*//:清除图案空间。
  • x:交换模式空间和保持空间。注意,无论loss匹配与否,该命令都会执行。
    • 如果匹配,我们只执行 … 大括号loss内的所有命令(上面列出),因此模式空间为空。因此这会将保留空间设置为空白。 (我不确定这是{}真的必要的,但这可能是个好主意。)
    • 如果loss不匹配,则模式空间包含当前行;所以这会将当前行放入保留空间。

据我所知,如果输入如您所描述的那样,这将非常有效。

  • 如果输入的第一行包含loss,那么这将打印一个空行和输入的前三行(即该loss行及其后面的两行)。
  • 如果输入的最后一行或倒数第二行包含loss,那么这将不会打印它,因为该行之后没有两行loss- 因为sed当遇到文件末尾时会中止命令序列。如果您想通过打印该loss行、该行之前的行以及之后的(单)行(如果有)来处理这种情况,请执行以下操作:

    sed -n '/loss/ { x; G; p; n; p; n; p; s/.*// }; x' pingFailed.txt > pingFailed1.txt
    

    分别读取并打印“after”两行。

相关内容