☰
03-Nginx正则表达式完全指南(location匹配 + rewrite重写 + 条件判断 + 变量提取)
2026/10/1 18:38:59 网站建设 项目流程

摘要:本文详细介绍 Nginx 中正则表达式的使用方法,涵盖 location 匹配、rewrite 重写、条件判断、变量提取和实战案例。通过本文档,你将掌握 Nginx 正则表达式的核心语法,能够灵活处理复杂的 URL 匹配和重写需求。

关键词:Nginx、正则表达式、location、rewrite、URL重写、条件判断、变量提取

适合人群:有 Nginx 基础的开发者、想深入学习 URL 匹配的工程师

阅读时间:约 40 分钟

版本信息:Nginx 1.24+ | PCRE 库支持


文章目录

  • 1. 正则表达式基础
    • 1.1 什么是正则表达式
    • 1.2 Nginx 正则语法
    • 1.3 常用正则符号
  • 2. location 正则匹配
    • 2.1 location 匹配优先级
    • 2.2 精确匹配(=)
    • 2.3 优先前缀匹配(^~)
    • 2.4 正则匹配(~ 和 ~*)
    • 2.5 实战:完整 location 配置
  • 3. rewrite 重写规则
    • 3.1 rewrite 语法
    • 3.2 基础重写示例
    • 3.3 正则捕获组
    • 3.4 条件重写
    • 3.5 实战:URL 重写案例
      • 案例 1:旧域名迁移
      • 案例 2:API 版本管理
      • 案例 3:SEO 友好 URL
  • 4. 条件判断
    • 4.1 if 指令语法
    • 4.2 请求方法判断
    • 4.3 User-Agent 判断
    • 4.4 文件存在判断
    • 4.5 查询参数判断
  • 5. 变量提取
    • 5.1 内置变量
    • 5.2 正则捕获变量
    • 5.3 自定义变量
    • 5.4 map 指令
  • 6. 实战案例
    • 实战 1:图片服务器
    • 实战 2:API 网关路由
    • 实战 3:多语言网站
    • 实战 4:防盗链配置
  • 7. 常见问题 FAQ
  • 8. 学习资源与建议
    • 学习建议
    • 官方资源
    • 推荐工具

1. 正则表达式基础

1.1 什么是正则表达式

正则表达式(Regular Expression)是一种用于匹配字符串模式的工具。在 Nginx 中,正则表达式主要用于:

  • location 匹配:根据 URL 模式选择处理方式
  • rewrite 重写:将 URL 重写为新的格式
  • 条件判断:根据请求特征执行不同逻辑
  • 变量提取:从 URL 中提取参数

1.2 Nginx 正则语法

Nginx 使用 PCRE(Perl Compatible Regular Expressions)库,支持以下匹配操作符:

操作符说明示例
~区分大小写的正则匹配~ \.php$
~*不区分大小写的正则匹配`~* .(jpg
!~区分大小写的正则不匹配!~ \.php$
!~*不区分大小写的正则不匹配`!~* .(jpg

1.3 常用正则符号

Nginx 支持的正则符号:

符号说明示例匹配
.任意单个字符a.cabc, a1c, a-c
*0 次或多次ab*cac, abc, abbc
+1 次或多次ab+cabc, abbc
?0 次或 1 次ab?cac, abc
^字符串开头^abcabc, abcdef
$字符串结尾abc$abc, 123abc
[]字符集合[abc]a, b, c
[^]否定字符集合[^abc]除 a,b,c 外的字符
()分组(abc)+abc, abcabc
``或`a
\d数字\d+123, 456
\w单词字符\w+abc, 123
\s空白字符\s+空格, 制表符

💡提示:Nginx 的正则表达式不需要使用/包裹,直接使用模式即可。


2. location 正则匹配

2.1 location 匹配优先级

Nginx 的 location 匹配有严格的优先级顺序:

1. = 精确匹配(最高优先级) 2. ^~ 优先前缀匹配 3. ~ 区分大小写的正则匹配 4. ~* 不区分大小写的正则匹配 5. / 通用前缀匹配(最低优先级)

匹配流程:

请求到达 → 检查精确匹配(=) → 检查优先前缀匹配(^~) → 检查正则匹配(~/~*) → 使用最长前缀匹配

2.2 精确匹配(=)

精确匹配整个 URL 路径:

# 只匹配 / location = / { return 200 "首页"; } # 只匹配 /about location = /about { return 200 "关于页面"; } # 只匹配 /api/v1/users location = /api/v1/users { proxy_pass http://backend; }

💡提示:精确匹配优先级最高,但只匹配完全相同的 URL。

2.3 优先前缀匹配(^~)

匹配 URL 前缀,且停止正则匹配:

# 匹配 /images/ 开头的所有路径 location ^~ /images/ { root /var/www/static; expires 30d; } # 匹配 /static/ 开头的所有路径 location ^~ /static/ { root /var/www; expires 30d; }

💡提示:^~匹配成功后,Nginx 不再检查正则匹配,适合静态资源。

2.4 正则匹配(~ 和 ~*)

使用正则表达式匹配 URL:

# 区分大小写:匹配 .php 文件 location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; } # 不区分大小写:匹配图片文件 location ~* \.(jpg|jpeg|png|gif|ico|svg)$ { root /var/www/images; expires 30d; add_header Cache-Control "public, immutable"; } # 不区分大小写:匹配 CSS/JS 文件 location ~* \.(css|js)$ { root /var/www/static; expires 7d; } # 匹配特定格式的文档 location ~* \.(pdf|doc|docx|xls|xlsx)$ { root /var/www/documents; }

2.5 实战:完整 location 配置

server { listen 80; server_name example.com; # 1. 精确匹配首页 location = / { root /var/www/html; index index.html; } # 2. 优先前缀匹配:静态资源 location ^~ /static/ { root /var/www; expires 30d; } # 3. 正则匹配:图片 location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ { root /var/www/images; expires 30d; } # 4. 正则匹配:CSS/JS location ~* \.(css|js)$ { root /var/www/static; expires 7d; } # 5. 正则匹配:PHP location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; } # 6. 通用前缀匹配:API location /api { proxy_pass http://backend; } # 7. 默认匹配 location / { root /var/www/html; index index.html; try_files $uri $uri/ =404; } }

3. rewrite 重写规则

3.1 rewrite 语法

rewrite指令用于重写 URL:

rewrite regex replacement [flag];

参数说明:

参数说明
regex正则表达式模式
replacement替换后的 URL
flag标志(last, break, redirect, permanent)

flag 说明:

标志说明使用场景
last重写后继续匹配新的 location内部重写
break重写后停止匹配,直接处理内部重写
redirect302 临时重定向临时跳转
permanent301 永久重定向永久跳转

3.2 基础重写示例

将旧 URL 重写到新 URL:

server { listen 80; server_name example.com; # 301 永久重定向 rewrite ^/old-page$ /new-page permanent; # 302 临时重定向 rewrite ^/temp-page$ /new-page redirect; # 内部重写(不改变浏览器 URL) rewrite ^/api/v1/(.*)$ /api/v2/$1 last; }

3.3 正则捕获组

使用()捕获 URL 中的部分:

server { listen 80; server_name example.com; # 捕获用户 ID rewrite ^/user/(\d+)$ /profile?id=$1 last; # 捕获年份、月份、日期 rewrite ^/blog/(\d{4})/(\d{2})/(\d{2})/(.*)$ /article?year=$1&month=$2&day=$3&slug=$4 last; # 捕获文件扩展名 rewrite ^/download/(.*)\.(zip|tar\.gz)$ /files/$1.$2 last; }

捕获组说明:

  • $1:第一个捕获组
  • $2:第二个捕获组
  • 以此类推

3.4 条件重写

使用if指令进行条件重写:

server { listen 80; server_name example.com; # 根据 User-Agent 重写 if ($http_user_agent ~* "mobile") { rewrite ^/$ /mobile.html last; } # 根据 Cookie 重写 if ($http_cookie ~* "theme=dark") { rewrite ^/$ /dark-theme.html last; } # 根据查询参数重写 if ($arg_version = "v1") { rewrite ^/api/(.*)$ /api/v1/$1 last; } }

💡提示:Nginx 官方建议尽量少用if,因为其行为在某些情况下不可预测。

3.5 实战:URL 重写案例

案例 1:旧域名迁移

server { listen 80; server_name old.example.com; # 所有请求 301 到新域名 rewrite ^(.*)$ https://new.example.com$1 permanent; }

案例 2:API 版本管理

server { listen 80; server_name api.example.com; # 默认使用 v2 rewrite ^/api/(.*)$ /api/v2/$1 last; # 指定版本 location ~ ^/api/v(\d+)/ { proxy_pass http://backend; } }

案例 3:SEO 友好 URL

server { listen 80; server_name blog.example.com; # /2024/01/01/my-post → /post?slug=my-post&date=2024-01-01 rewrite ^/(\d{4})/(\d{2})/(\d{2})/(.+)$ /post?slug=$4&date=$1-$2-$3 last; # /category/tech → /posts?category=tech rewrite ^/category/(.+)$ /posts?category=$1 last; # /tag/nginx → /posts?tag=nginx rewrite ^/tag/(.+)$ /posts?tag=$1 last; }

4. 条件判断

4.1 if 指令语法

Nginx 的if指令用于条件判断:

if (condition) { # 配置指令 }

条件类型:

条件类型示例说明
变量比较$request_method = POST变量等于某值
正则匹配$http_user_agent ~* "mobile"正则匹配
文件存在-f $request_filename文件存在
目录存在-d $request_filename目录存在
文件/目录/链接不存在!-e $request_filename不存在
可执行文件-x $request_filename可执行

4.2 请求方法判断

server { listen 80; server_name api.example.com; # 只允许 GET 和 POST if ($request_method !~ ^(GET|POST)$) { return 405; } # GET 请求处理 if ($request_method = GET) { # 处理 GET 请求 } # POST 请求处理 if ($request_method = POST) { # 处理 POST 请求 } }

4.3 User-Agent 判断

server { listen 80; server_name example.com; # 移动端跳转 if ($http_user_agent ~* "(mobile|android|iphone|ipad)") { rewrite ^/$ /mobile.html last; } # 搜索引擎爬虫 if ($http_user_agent ~* "(googlebot|baiduspider|bingbot)") { # 允许爬虫访问 } # 禁止特定爬虫 if ($http_user_agent ~* "(badbot|evilbot)") { return 403; } }

4.4 文件存在判断

server { listen 80; server_name example.com; root /var/www/html; # 如果文件不存在,返回 404 if (!-f $request_filename) { return 404; } # 如果目录不存在,创建 if (!-d $request_filename) { # 处理逻辑 } # SPA 路由支持 if (!-e $request_filename) { rewrite ^(.*)$ /index.html last; } }

4.5 查询参数判断

server { listen 80; server_name example.com; # 检查特定查询参数 if ($arg_token = "") { return 401; } # 检查多个参数 if ($arg_version = "v1") { rewrite ^/api/(.*)$ /api/v1/$1 last; } # 检查参数是否存在 if ($arg_debug) { # 调试模式 } }

💡提示:$arg_参数名可以获取 URL 查询参数。


5. 变量提取

5.1 内置变量

Nginx 提供了大量内置变量:

变量说明示例值
$uri当前请求的 URI/api/users
$request_uri完整请求 URI(含参数)/api/users?page=1
$request_method请求方法GET, POST
$scheme协议http, https
$host主机名example.com
$remote_addr客户端 IP192.168.1.100
$server_port服务器端口80, 443
$http_referer来源页面https://google.com
$http_user_agent客户端信息Mozilla/5.0…
$cookie_nameCookie 值session_id=abc123

5.2 正则捕获变量

使用正则表达式捕获 URL 中的值:

location ~ ^/user/(\d+)/profile$ { # $1 捕获用户 ID set $user_id $1; proxy_pass http://backend/users/$user_id; } location ~ ^/blog/(\d{4})/(\d{2})/(.+)$ { # $1: 年份, $2: 月份, $3: 文章标题 set $year $1; set $month $2; set $slug $3; proxy_pass http://backend/blog?year=$year&month=$month&slug=$slug; }

5.3 自定义变量

使用set指令创建自定义变量:

server { listen 80; server_name example.com; # 根据请求方法设置变量 set $api_version "v1"; if ($arg_version = "v2") { set $api_version "v2"; } # 根据 User-Agent 设置变量 set $device_type "desktop"; if ($http_user_agent ~* "mobile") { set $device_type "mobile"; } location /api { proxy_pass http://backend/$api_version/$device_type; } }

5.4 map 指令

使用map创建变量映射:

http { # 根据设备类型映射 map $http_user_agent $device_type { default "desktop"; "~*mobile" "mobile"; "~*tablet" "tablet"; } # 根据协议映射 map $scheme $is_https { default 0; https 1; } server { listen 80; server_name example.com; location / { proxy_pass http://backend/$device_type; proxy_set_header X-Device-Type $device_type; proxy_set_header X-HTTPS $is_https; } } }

💡提示:map指令比if更安全、更高效,推荐优先使用。


6. 实战案例

实战 1:图片服务器

server { listen 80; server_name images.example.com; root /var/www/images; # 按尺寸重写 location ~ ^/images/(.*)_(large|medium|small)\.(jpg|png)$ { set $filename $1; set $size $2; set $ext $3; # 检查缩略图是否存在 if (!-f $request_filename) { # 不存在则重写为原图 rewrite ^/images/(.*)_(large|medium|small)\.(jpg|png)$ /images/$1.$3 last; } } # 匹配所有图片 location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ { expires 30d; add_header Cache-Control "public, immutable"; } }

项目知识点:

  • 正则捕获组
  • 文件存在判断
  • 条件重写

实战 2:API 网关路由

server { listen 80; server_name gateway.example.com; # 版本路由 location ~ ^/api/v(\d+)/(.*)$ { set $version $1; set $path $2; # 根据版本转发到不同后端 if ($version = "1") { proxy_pass http://backend_v1/$path; } if ($version = "2") { proxy_pass http://backend_v2/$path; } proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 默认版本 location /api { rewrite ^/api/(.*)$ /api/v2/$1 last; } }

项目知识点:

  • 版本路由
  • 条件判断
  • 重写规则

实战 3:多语言网站

server { listen 80; server_name example.com; root /var/www/html; # 语言前缀匹配 location ~ ^/(en|zh|ja|ko)/(.*)$ { set $lang $1; set $path $2; # 检查语言文件是否存在 if (-f $document_root/$lang/$path) { rewrite ^/(en|zh|ja|ko)/(.*)$ /$lang/$2 last; } # 不存在则使用默认语言 rewrite ^/(en|zh|ja|ko)/(.*)$ /zh/$2 last; } # 默认语言 location / { try_files $uri $uri/ /zh/index.html; } }

项目知识点:

  • 多语言路由
  • 条件判断
  • 默认回退

实战 4:防盗链配置

server { listen 80; server_name images.example.com; root /var/www/images; location ~* \.(jpg|jpeg|png|gif|svg)$ { # 检查 Referer valid_referers none blocked server_names *.example.com; if ($invalid_referer) { # 返回防盗链图片 rewrite ^/ /watermark.jpg last; } expires 30d; add_header Cache-Control "public, immutable"; } }

项目知识点:

  • Referer 验证
  • 条件重写
  • 防盗链

7. 常见问题 FAQ

Q1:location 匹配顺序是什么?

A:匹配优先级:

1. = 精确匹配 2. ^~ 优先前缀匹配 3. ~ 区分大小写正则 4. ~* 不区分大小写正则 5. / 通用前缀匹配

Q2:rewrite 的 last 和 break 有什么区别?

A:区别如下:

  • last:重写后继续匹配新的 location
  • break:重写后停止匹配,直接处理当前 location
# last:重写后继续匹配 rewrite ^/old/(.*)$ /new/$1 last; # break:重写后停止 rewrite ^/old/(.*)$ /new/$1 break;

Q3:如何在 rewrite 中使用捕获组?

A:使用()捕获,$1,$2引用:

rewrite ^/user/(\d+)/profile$ /api/user?id=$1 last;

Q4:if 指令有什么注意事项?

A:Nginx 官方建议:

  • 尽量少用if
  • if中只能使用return,rewrite,proxy_pass等少数指令
  • 优先使用map替代if

Q5:如何调试正则表达式?

A:使用以下方法:

# 测试配置语法nginx-t# 查看错误日志tail-f/var/log/nginx/error.log# 使用在线工具测试# https://regex101.com/

8. 学习资源与建议

学习建议

1.先理解匹配优先级:理解 location 匹配顺序是核心
2.多用 map 少用 if:map更安全、更高效
3.善用测试命令:每次修改配置后,先用nginx -t测试语法
4.查看日志排错:遇到问题时,查看错误日志是最快的排错方法
5.使用在线工具:使用 regex101.com 测试正则表达式

官方资源

  • Nginx rewrite 模块
  • Nginx location 模块
  • PCRE 文档
  • Regex101 - 正则表达式测试工具

推荐工具

  • Regex101 - 正则表达式测试
  • Nginx Config - Nginx 配置生成器
  • curl - HTTP 请求测试

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询