如何解析混合分隔符的Nginx/Apache access.log并可选转换为JSON
混合多分隔符访问日志通用解析方案
核心思路
针对同时包含空格、方括号、双引号等多种分隔符的结构化日志,不要强行定义多分隔符切割,优先使用字段模式匹配逻辑:即先梳理每个字段的格式特征,直接按规则提取对应内容,完全避免分隔符冲突问题。
方法1:GNU awk FPAT模式匹配(最推荐)
GNU awk(即gawk)提供的FPAT参数可以直接定义每个字段的匹配规则,无需指定分隔符,完美适配Nginx/Apache默认访问日志场景。
适配Nginx日志的正则规则
FPAT = "([^ ]+)|(\\[.*?\\])|(\".*?\")"
规则分三个匹配分支:
[^ ]+:匹配无包裹的连续非空格字段,对应IP、状态码、响应字节数等\\[.*?\\]:匹配被方括号完整包裹的字段,对应访问时间".*?":匹配被双引号完整包裹的字段,对应请求行、referer、UA等
完整解析命令
gawk ' BEGIN { FPAT = "([^ ]+)|(\\[.*?\\])|(\".*?\")" } { # 按需去除字段的包裹符号 gsub(/\[|\]/, "", $4) # 去除时间的方括号 gsub(/"/, "", $5) # 去除请求行的双引号 gsub(/"/, "", $8) # 去除referer的双引号 gsub(/"/, "", $9) # 去除UA的双引号 # 按需求打印字段 print "$1 = " $1 print "$4 = " $4 print "$5 = " $5 print "$6 = " $6 print "$7 = " $7 print "$8 = " $8 print "$9 = " $9 print "---------------------" }' access.log
注:FPAT为GNU awk特有功能,MacOS默认自带的BSD awk不支持,可通过
brew install gawk安装后使用
输出转换为JSON格式
直接在awk中拼接JSON结构即可,示例:
gawk ' BEGIN { FPAT = "([^ ]+)|(\\[.*?\\])|(\".*?\")" } { gsub(/\[|\]/, "", $4) gsub(/"/, "", $5) gsub(/"/, "", $8) gsub(/"/, "", $9) printf "{\"ip\":\"%s\",\"time\":\"%s\",\"request\":\"%s\",\"status\":%d,\"body_bytes\":%d,\"referer\":\"%s\",\"ua\":\"%s\"}\n", $1, $4, $5, $6, $7, $8, $9 }' access.log
通用兼容方案(适配所有awk版本)
如果环境没有GNU awk,可使用match()函数逐段匹配提取,逻辑通用可适配所有复杂结构化日志:
awk '{ # 提取时间字段 match($0, /\[(.*?)\]/, time_arr) time = time_arr[1] # 提取请求行 match($0, /"([^"]+)"/, req_arr) request = req_arr[1] # 提取状态码、响应字节数 rest_str = substr($0, req_arr[0, "length"] + RSTART) split(rest_str, rest_arr, " ") status = rest_arr[2] body_bytes = rest_arr[3] # 剩余referer、UA字段同理用match匹配双引号即可 }' access.log
内容的提问来源于stack exchange,提问作者GLK
相关产品推荐
相关产品推荐

