如何修改Awk命令或用Python/正则提取Ping日志中连续2次及以上超时的行(含最后一行)
首先看你的需求:从给定的Ping日志里提取连续出现2次及以上的请求超时行,单次超时忽略。你原来的Awk命令之所以漏掉最后一行,是因为它只在当前行和上一行都是超时的时候打印上一行,没法处理连续多行的最后一行,也没考虑文件末尾的连续超时块。
先回顾下你的日志和预期输出:
原始日志
2021/02/15 14:22:27 : Reply[1] from 10.10.10.1: bytes=32 time=31.9 ms TTL=244 jitter=0.00 ms
2021/02/15 14:22:27 : Reply[2] from 10.10.10.1: bytes=32 time=32.5 ms TTL=244 jitter=0.03 ms
2021/02/15 14:22:28 : 10.10.10.1: request timed out
2021/02/15 14:22:28 : Reply[4] from 10.10.10.1: bytes=32 time=29.9 ms TTL=244 jitter=0.28 ms
2021/02/15 14:22:29 : Reply[5] from 10.10.10.1: bytes=32 time=27.4 ms TTL=244 jitter=0.42 ms
2021/02/15 14:22:29 : Reply[6] from 10.10.10.1: bytes=32 time=31.3 ms TTL=244 jitter=0.63 ms
2021/02/15 14:22:30 : 10.10.10.1: request timed out
2021/02/15 14:22:31 : 10.10.10.1: request timed out
2021/02/15 14:22:31 : 10.10.10.1: request timed out
2021/02/15 14:22:32 : Reply[10] from 10.10.10.1: bytes=32 time=33.8 ms TTL=244 jitter=0.91 ms
预期输出
2021/02/15 14:22:30 : 10.10.10.1: request timed out
2021/02/15 14:22:31 : 10.10.10.1: request timed out
2021/02/15 14:22:31 : 10.10.10.1: request timed out
修正后的Awk方案
核心思路是用缓冲区保存连续的超时行,遇到非超时行或文件结束时,判断缓冲区长度是否≥2,符合条件就输出所有内容。
awk -F " : " ' { # 如果当前行是超时记录,加入缓冲区 if ($2 ~ /request timed out/) { buffer[++count] = $0 } else { # 遇到非超时行,检查缓冲区是否有≥2条记录,是则输出 if (count >= 2) { for (i=1; i<=count; i++) { print buffer[i] } } # 重置缓冲区和计数 count = 0 delete buffer } } # 文件结束前,再检查一次缓冲区,处理末尾的连续超时 END { if (count >= 2) { for (i=1; i<=count; i++) { print buffer[i] } } }' your_ping_log.txt
这个脚本会完美覆盖所有场景:既不会漏掉连续超时的最后一行,也会自动忽略单次超时的记录。
Python解决方案
如果更熟悉Python,这个逻辑同样容易实现,用列表作为缓冲区:
with open("your_ping_log.txt", "r") as log_file: log_lines = log_file.read().splitlines() timeout_buffer = [] for line in log_lines: if "request timed out" in line: timeout_buffer.append(line) else: # 遇到非超时行,检查缓冲区长度 if len(timeout_buffer) >= 2: print("\n".join(timeout_buffer)) timeout_buffer = [] # 处理文件末尾的连续超时块 if len(timeout_buffer) >= 2: print("\n".join(timeout_buffer))
运行这个脚本就能得到你想要的输出,逻辑清晰,容易修改和扩展。
正则表达式方案
如果想用正则一次性匹配所有符合条件的连续超时块,可以用多行模式匹配:
import re with open("your_ping_log.txt", "r") as log_file: log_content = log_file.read() # 匹配连续的超时行块 timeout_blocks = re.findall(r'(^.*request timed out$\n?)+', log_content, re.MULTILINE) for block in timeout_blocks: # 统计块内的行数,至少2行则输出 line_num = block.count('\n') + 1 if line_num >= 2: print(block.strip())
这个方法适合一次性处理整个日志内容,通过正则把所有连续超时的块提取出来,再筛选出符合行数要求的块输出。
内容的提问来源于stack exchange,提问作者blue212121

