转自: http://www.iigrowing.cn/nginx-zhong-de-zheng-ze-biao-da-shi.html
所有的Nginx内置变量都可以通过if指令和正则表达式来进行匹配,并且根据匹配结果进行一些操作,如下:
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_cookie ~* "id=([^;] +)(?:;|$)" ) {
set $id $1;
}
使用符号~*
和~
模式匹配的正则表达式:
~
为区分大小写的匹配。~*
不区分大小写的匹配(匹配firefox的正则同时匹配FireFox)。!~
和!~*
意为“不匹配的”。Nginx在很多模块中都有内置的变量,常用的内置变量在HTTP核心模块中,这些变量都可以使用正则表达式进行匹配。
可能这个指令是我们平时使用正则匹配用的最多的指令:
location ~ .*\.php?$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/wwwsite/test.com/$fastcgi_script_name;
include fcgi.conf;
}
几乎每个基于LEMP的主机都会有如上一段代码。他的匹配规则类似于if
指令,不过他多了三个标识符,^~
、=
、@
。并且它没有取反运算符!
,这三个标识符的作用分别是:
^~
标识符后面跟一个字符串。Nginx将在这个字符串匹配后停止进行正则表达式的匹配(location指令中正则表达式的匹配的结果优先使用),如:location ^~ /images/
,你希望对/images/
这个目录进行一些特别的操作,如增加expires
头,防盗链等,但是你又想把除了这个目录的图片外的所有图片只进行增加expires
头的操作,这个操作可能会用到另外一个location,例如:location ~* \.(gif|jpg|jpeg)$
,这样,如果有请求/images/1.jpg
,nginx如何决定去进行哪个location中的操作呢?结果取决于标识符^~
,如果你这样写:location /images/
,这样nginx会将1.jpg
匹配到location ~* \.(gif|jpg|jpeg)$
这个location中,这并不是你需要的结果,而增加了^~
这个标识符后,它在匹配了/images/
这个字符串后就停止搜索其它带正则的location。
=
表示精确的查找地址,如location = /
它只会匹配uri为/
的请求,如果请求为/index.html
,将查找另外的location,而不会匹配这个,当然可以写两个 location,location = /
和location /
,这样/index.html
将匹配到后者,如果你的站点对/
的请求量较大,可以使用这个方法来加快请求的响应速度。
@
表示为一个location进行命名,即自定义一个location,这个location不能被外界所访问,只能用于Nginx产生的子请求,主要为error_page
和try_files
。
注意,这3个标识符后面不能跟正则表达式,虽然配置文件检查会通过,而且没有任何警告,但是他们并不会进行匹配。
综上所述,location指令对于后面值的匹配顺序为:
=
的location会最先进行匹配,如果请求uri匹配这个location,将对请求使用这个location的配置。^~
这个标识符,匹配停止返回这个location的配置。server_name用于配置基于域名或IP的虚拟主机,这个指令也是可以使用正则表达式的,但是注意,这个指令中的正则表达式不用带任何的标识符,但是必须以~
开头:
server {
server_name www.example.com ~^www\d+\.example\.com$;
}
server_name指令中的正则表达式可以使用引用,高级的应用可以查看这篇文章:在server_name中使用正则表达式
这个指令按照CGI标准来设置SCRIPT_FILENAME (SCRIPT_NAME)和PATH_INFO变量,它是一个被分割成两部分(两个引用)的正则表达式。如下:
location ~ ^.+\.php {
(...)
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
(...)
}
第一个引用(.+\.php)
加上/path/to/php
将作为SCRIPT_FILENAME
,第二个引用(.*)
为PATH_INFO
,例如请求的完整URI为show.php/article/0001
,则上例中SCRIPT_FILENAME
的值为/path/to/php /show.php
,PATH_INFO
则为/article/0001
。
这个指令通常用于一些通过PATH_INFO美化URI的框架(例如CodeIgniter)。
通过正则表达式来指定在哪些浏览器中禁用gzip压缩。
gzip_disable "msie6";
这个指令应该也是用的比较多的,它需要使用完整的包含引用的正则表达式:
rewrite "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/$1/$1$2/$1$2$3.png;
通常环境下我们会把它和if结合来使用:
if ($host ~* www\.(.*)) {
set $host_without_www $1;
rewrite ^(.*)$ http://$host_without_www$1 permanent; # $1为'/foo',而不是'www.mydomain.com/foo'
}
需要注意的是rewrite后面的第一个正则参数永远是只对URI进行匹配,而不是对完整的带主机头的URL,如上例中,if语句来判断主机头,如果匹配 www\.(.*)
,则设置一个变量$host_without_www
的值为www\.(.*)
的引用,如果上例中的请求URL为www.mydomain.com/foo
,则$host_without_www
的值为mydomain.com
,而下面的rewrite指令中,第一个正则表达式的引用将为/foo
,则最终通过这个重写后的请求URL为http://mydomain.com/foo
。
首先确定在编译pcre时加了enable-utf8参数,如果没有,请重新编译pcre,然后就可以在Nginx的配置文件中使用这样的正则:"(*UTF8)^/[\x{4e00}-\x{9fbf}]+)$"
注意引号和前面的(*UTF8)
,(*UTF8)
将告诉这个正则切换为UTF8模式。
通常我们在Nginx安装之前会编译安装pcre,它自带一个小工具:pcretest,使用方法以下:
[root@backup conf]# pcretest
PCRE version 8.10 2010-06-25
re> /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3,3}$/ ###这是一个匹配IP的正则
data> 192.168.10.1
0: 192.168.10.1
1: 192
2: .1
3: 1
data> 666.666.666.666
No match
data> 255.255.255.255
0: 255.255.255.255
1: 255
2: .255
3: 255
data> 0.0.0.0
0: 0.0.0.0
1: 0
2: .0
3: 0
data> 666777
No match
匹配中文:
[root@backup conf]# pcretest
PCRE version 8.10 2010-06-25
re> /^[\x{4e00}-\x{9fbf}]+/8
data> 测试
0: \x{6d4b}\x{8bd5}
data> Nginx模块参考手册中文版
No match
data> 参考手册中文版
0: \x{53c2}\x{8003}\x{624b}\x{518c}\x{4e2d}\x{6587}\x{7248}