如何在首先检查接下来的 3 行后删除行
How to delete lines after first checking next 3 lines
我有一个与此类似的文本文件
00:00:24.752
8,594
3,847
0
00:00:25.228
0
1,692
0
00:00:25.738
6,548
5,304
0
00:00:26.248
1,807
417
0
00:00:26.758
3,913
5,335
0
00:00:26.792
0
00:00:27.234
0
00:00:27.268
0
0
0
00:00:27.778
9,903
2,345
0
00:00:27.812
0
00:00:28.322
0
9,501
0
这是网络流量,第一部分是时间戳,后两部分是发送和接收的流量。第三个是零,我不知道为什么会在那里。
所以我的目标是只保留流量值至少为 sent/receive 的行,并且每次都删除第三个 0。所以我会得到这样的结果。
00:00:24.752
8,594
3,847
00:00:25.228
0
1,692
00:00:25.738
6,548
5,304
00:00:26.248
1,807
417
00:00:26.758
3,913
5,335
00:00:27.778
9,903
2,345
00:00:28.322
0
9,501
尝试过使用 awk 检查当前行的长度,如果该行少于 8 个字符,则打印该行和下 2 个字符。但是由于文件并不总是至少有 2 个值在时间戳之后它无法正常工作。
awk '
/[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}/ {
if (NR > 1) p()
i = 0
}
{ buf[++i] = [=10=] }
END { p() }
function p() {
if (buf[2] || buf[3]) {
print buf[1]
print buf[2]
print buf[3]
}
delete buf
}' file
p
是一个函数,如果第 2 行和第 3 行不为空或为零,则打印缓冲行,并清除缓冲区。只要看到时间戳(并且它不是文件中的第一行)以及遇到 EOF 时就会调用它。所以上面的脚本基本上缓冲了两个时间戳之间的行,如果它们满足时间戳之后至少应该有两行的标准,并且它们不应该为零,则打印它们。
这可能适合您 (GNU sed):
sed '/:/!{H;$!d};x;/\n.*\n.*\n/{/\n0\n0\n0/!s/\n0$//p};x;h;d' file
如果当前行不是时间戳(不包含 :
),则将其附加到保留 space,如果不是最后一行,则将其删除。
如果当前行是最后一行或时间戳,则切换到保留 space 并检查前一条记录是否包含 4 行以及最后 3 行是否未归零,如果是则删除记录的最后一行并打印修改后的记录。
换回模式 space,用当前行(时间戳)替换保留 space 并将其删除。
N.B。删除一行时,不会对当前行进行进一步的 sed 处理。
如果你想省略所有第 4 行,这是实现此目的的 awk 脚本:
awk 'RN % 4{print}' input.txt
您想要的输出结果。
我有一个与此类似的文本文件
00:00:24.752
8,594
3,847
0
00:00:25.228
0
1,692
0
00:00:25.738
6,548
5,304
0
00:00:26.248
1,807
417
0
00:00:26.758
3,913
5,335
0
00:00:26.792
0
00:00:27.234
0
00:00:27.268
0
0
0
00:00:27.778
9,903
2,345
0
00:00:27.812
0
00:00:28.322
0
9,501
0
这是网络流量,第一部分是时间戳,后两部分是发送和接收的流量。第三个是零,我不知道为什么会在那里。
所以我的目标是只保留流量值至少为 sent/receive 的行,并且每次都删除第三个 0。所以我会得到这样的结果。
00:00:24.752
8,594
3,847
00:00:25.228
0
1,692
00:00:25.738
6,548
5,304
00:00:26.248
1,807
417
00:00:26.758
3,913
5,335
00:00:27.778
9,903
2,345
00:00:28.322
0
9,501
尝试过使用 awk 检查当前行的长度,如果该行少于 8 个字符,则打印该行和下 2 个字符。但是由于文件并不总是至少有 2 个值在时间戳之后它无法正常工作。
awk '
/[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}/ {
if (NR > 1) p()
i = 0
}
{ buf[++i] = [=10=] }
END { p() }
function p() {
if (buf[2] || buf[3]) {
print buf[1]
print buf[2]
print buf[3]
}
delete buf
}' file
p
是一个函数,如果第 2 行和第 3 行不为空或为零,则打印缓冲行,并清除缓冲区。只要看到时间戳(并且它不是文件中的第一行)以及遇到 EOF 时就会调用它。所以上面的脚本基本上缓冲了两个时间戳之间的行,如果它们满足时间戳之后至少应该有两行的标准,并且它们不应该为零,则打印它们。
这可能适合您 (GNU sed):
sed '/:/!{H;$!d};x;/\n.*\n.*\n/{/\n0\n0\n0/!s/\n0$//p};x;h;d' file
如果当前行不是时间戳(不包含 :
),则将其附加到保留 space,如果不是最后一行,则将其删除。
如果当前行是最后一行或时间戳,则切换到保留 space 并检查前一条记录是否包含 4 行以及最后 3 行是否未归零,如果是则删除记录的最后一行并打印修改后的记录。
换回模式 space,用当前行(时间戳)替换保留 space 并将其删除。
N.B。删除一行时,不会对当前行进行进一步的 sed 处理。
如果你想省略所有第 4 行,这是实现此目的的 awk 脚本:
awk 'RN % 4{print}' input.txt
您想要的输出结果。