我正在尝试使用 清理文本文件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”两行。