如何使用Regex在指定时间窗口内匹配日志中的3条及以上字符串
用正则+脚本实现日志时间窗口内的重复请求检测
嘿,咱们来解决这个日志分析的问题!你需要捕捉到特定请求在2秒或6秒窗口内出现3次及以上的情况对吧?首先得明确:单纯靠正则表达式本身没法直接计算时间差——毕竟正则只是文本模式匹配工具,没有时间运算的能力。但我们可以把正则匹配目标请求的能力,和awk这类能处理时间戳的脚本工具结合起来,这也是日志分析里的常规操作。
先看你的日志,目标请求的特征很明确,就是包含这段内容:
"POST /?wc-ajax=get_refreshed_fragments HTTP/2.0"
日志里的时间格式是[DD/MMM/YYYY:HH:MM:SS +ZZZZ],我们可以先提取这些目标条目,再计算时间窗口内的出现次数。
需求1:捕捉2秒内出现3条及以上的目标请求
我用awk来写这个脚本,它处理时间转换和计数非常方便:
脚本代码
BEGIN { # 定义日志里的时间格式 time_fmt = "[%d/%b/%Y:%H:%M:%S %z]" # 匹配目标请求的正则(注意转义特殊字符) target_regex = "POST /\\?wc-ajax=get_refreshed_fragments" # 设置时间窗口为2秒 window = 2 # 设置触发阈值:3次及以上 threshold = 3 } # 只处理包含目标请求的行 $0 ~ target_regex { # 提取时间字符串:从第5个字段里去掉前后的[] time_str = substr($5, 2, length($5)-2) # 把时间字符串转换成时间戳(秒数,方便计算差值) timestamp = mktime(gensub(/([0-9]+)\/([A-Za-z]+)\/([0-9]+):([0-9]+):([0-9]+):([0-9]+) ([+-][0-9]+)/, "\\3 \\2 \\1 \\4 \\5 \\6", "g", time_str)) # 把当前时间戳加入数组 timestamps[++count] = timestamp # 清理超出时间窗口的旧记录:如果最早的时间戳比当前时间早2秒以上,就删掉 while (timestamps[1] < timestamp - window) { delete timestamps[1] # 重新整理数组(删掉第一个元素后,后面的元素往前挪) for (i=1; i<=count; i++) timestamps[i] = timestamps[i+1] count-- } # 如果当前窗口内的记录数达到阈值,就输出结果 if (count >= threshold) { print "✅ 检测到2秒窗口内出现" count "次目标请求:" # 输出最近的3条(及以上)相关记录 for (i=count-threshold+1; i<=count; i++) { print " " lines[i] } print "------------------------" } # 保存当前行的完整内容,方便后续输出 lines[count] = $0 }
使用方法
把上面的代码保存成detect_2s.awk文件,然后在终端里运行:
awk -f detect_2s.awk 你的日志文件名.log
需求2:捕捉6秒内出现3条及以上的目标请求
这个更简单,只需要把上面脚本里的window变量改成6就行,其他代码完全不用动:
修改后的关键片段
BEGIN { time_fmt = "[%d/%b/%Y:%H:%M:%S %z]" target_regex = "POST /\\?wc-ajax=get_refreshed_fragments" window = 6 # 这里改成6秒的窗口 threshold = 3 }
保存成detect_6s.awk,运行方式和之前一样:
awk -f detect_6s.awk 你的日志文件名.log
关于纯正则的小提醒
如果你想着只用正则来实现(比如在某些只支持正则的工具里),那几乎是不可能的——因为正则没法跟踪时间戳并计算差值,它只能匹配固定的文本模式。比如你可以写正则匹配3条连续的目标请求,但没法判断它们的时间差是否在2秒或6秒内。所以结合脚本工具才是更实际的解决方案哦。
内容的提问来源于stack exchange,提问作者Fasolechka
相关产品推荐
相关产品推荐

