应使用双引号分隔再提取请求行第二字段,然后取其空格分割后的第二列,或用正则匹配首空格后非空白字符,以稳定获取URL路径。

直接用空格切分 Nginx 日志容易出错,因为 URL 路径里可能含空格(比如 POST 请求体被误记)、查询参数带特殊字符,甚至引号嵌套。关键不是“怎么切”,而是“怎么稳准提取路径”——得绕过干扰,聚焦真正要的字段。
先确认日志格式再动手
Nginx 默认 log_format combined 的结构是固定的:
192.168.1.1 - - [10/Jan/2024:12:34:56 +0800] "GET /api/v1/users?limit=10 HTTP/1.1" 200 1234 "https://example.com" "Mozilla/5.0"
你要的 URL 路径(如 /api/v1/users?limit=10)藏在第二个双引号里,且是该引号内第一个空格之后、第二个空格之前的内容。不能靠 $7 硬取——字段数会因 referer 或 UA 中的空格而偏移。
用双引号当分隔符,安全提取请求行
以 " 为域分隔符,取第 2 个域,就拿到了完整的请求行:
-
awk -F'"' '{print $2}' access.log→ 输出:GET /api/v1/users?limit=10 HTTP/1.1 - 再对这行按空格切,取第 2 列:
awk -F'"' '{split($2,a," "); print a[2]}' access.log
这样不管 query string 里有多少个 %20 或空格,都不会影响路径主体的提取。
更健壮:用正则匹配路径段
如果日志里出现异常格式(比如路径本身含空格、引号不闭合),推荐用 match() 直接定位:
awk -F'"' 'NF>=2 {match($2, / [^[:space:]]+/); if(RSTART) print substr($2, RSTART+1)}' access.log- 它在第二个引号内容中,找第一个空格后连续非空白字符,精准捕获路径,跳过协议和版本干扰
提取后做统计或过滤就顺了
拿到干净路径后,后续操作就很直观:
- 查访问最多的前 10 个路径:
... | sort | uniq -c | sort -nr | head -10 - 只看 404 请求的路径:
awk '$9==404 {print $7}' access.log | ...(前提是字段稳定) - 统计某路径的总耗时:
awk '$7 ~ /^\/api\// {sum += $11} END {print sum}' access.log(假设 $11 是$request_time)
不复杂但容易忽略。


















