如何用正则表达式合并Apache日志中的重复条目?
基于正则分组忽略指定字段合并Apache重复日志
核心思路
uniq只能按整行内容去重,无法忽略时间戳、字节数这类动态变化的字段。我们可以用awk结合正则分组提取关键标识字段,以此作为去重依据——保留IP地址、请求内容、状态码等核心信息的唯一性,同时自动忽略时间戳和传输字节数的差异。
具体实现(假设你的6分组正则为Apache Combined格式)
假设你的日志匹配正则为:
^(\S+) - - \[([^\]]+)\] "([^"]+)" (\d+) (\d+) "([^"]+)"$
对应6个分组:
- 客户端IP地址
- 请求时间戳(需忽略)
- 请求行(方法+路径+协议)
- HTTP状态码
- 传输字节数(需忽略)
- User-Agent(或Referer,依日志格式而定)
基础去重(仅保留首次出现的日志行)
执行以下awk命令,自动过滤重复条目:
BEGIN { log_regex = "^(\\S+) - - \\[([^\\]]+)\\] \"([^\"]+)\" (\\d+) (\\d+) \"([^\"]+)\"$" } { if (match($0, log_regex, groups)) { # 构造去重标识:仅保留需关注的分组(排除时间戳和字节数) unique_key = groups[1] "|" groups[3] "|" groups[4] "|" groups[6] # 仅打印首次出现的条目 if (!(unique_key in recorded)) { print $0 recorded[unique_key] = 1 } } }
将上述命令保存为dedup_logs.awk,然后运行:
awk -f dedup_logs.awk your_apache_log.log > deduped_logs.log
进阶:统计重复次数
如果需要知道每条日志的重复次数,可修改脚本为:
BEGIN { log_regex = "^(\\S+) - - \\[([^\\]]+)\\] \"([^\"]+)\" (\\d+) (\\d+) \"([^\"]+)\"$" } { if (match($0, log_regex, groups)) { unique_key = groups[1] "|" groups[3] "|" groups[4] "|" groups[6] # 累计重复次数 count[unique_key]++ # 保存首次出现的日志内容 if (count[unique_key] == 1) { original_line[unique_key] = $0 } } } END { # 输出每条唯一日志及重复次数 for (key in count) { print original_line[key] " [重复次数: " count[key] "]" } }
自定义适配
如果你的正则分组顺序或结构不同,只需调整unique_key中的groups[X]索引即可——比如你的分组2是时间戳、分组5是字节数,就始终排除这两个索引,保留其余分组拼接成去重标识。
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

