正则表达式的结构

完整的正则表达式是由很多小的模块组成的,而每个小的模块都很简单,但是这些符号如果是随意结合的话,可以有无穷无尽的组合

正则表达式除了信手拈来的\d,\w+,\s+,.*等等,有些规则用的比较少容易被遗忘,这里基本都是linux命令行上的正则表达式容易被忽略的几点,熟练了之后,对于编写shell脚本会有很大的帮助,操作命令行也会更舒畅,对于脚本语言正则表达式一脉相承,只要掌握了思想方法,其它就只需要写出pattern就大功告成了

1:行的开始和结束

linux下egrep任何人都会用,比如查看nginx配置文件监听的是哪个端口:

[lihui@localhost ~]# egrep 'listen' /usr/local/nginx/conf/nginx.conf
		listen       80;

或者查看下pid文件存放目录:

[lihui@localhost ~]# egrep '^pid' /usr/local/nginx/conf/nginx.conf
pid        /usr/local/nginx/logs/nginx.pid;

也许你更习惯用cat打开文件,然后管道来进行grep,效果一样;这里正则表达式里有一个符号^,代表的是行的开始,另一个符号$,代表的是行的末尾,这里需要注意两点:

(1)假如pattern写的是^listen$,匹配的是是某行以listen开头和结尾,没有任何其它字符

(2)假如pattern写的是^$,匹配的其实是一个空行,而且没有空格

 

2:字符组,匹配其中一个字符

假如你需要匹配的内容不是十分确定,甚至要匹配出仅仅某个字符不同的部分,可以通过正则表达式的结构体【】,然后将期望匹配到的字符都写在里面,简单来说意思就是[abc]能分别匹配a或者b或者c,假如你忘了某个字符,这倒是一个好方法

[lihui@localhost ~]# egrep 'li[sb]t[en]n' /usr/local/nginx/conf/nginx.conf
		listen       80;

字符还可以通过一个连接符-来表示一个范围,比如[0-9]匹配一个个位数字,[a-z]匹配一个字母,列举一个简单例子:

[lihui@localhost ~]# egrep ' [0-9][0-9];' /usr/local/nginx/conf/nginx.conf
		keepalive_timeout 60;
		listen       80;

这里匹配的是前面有一个空格,然后一个两位数字,接着分号,本意仅仅匹配出80,结果不凑巧这里的60也满足了这种条件,所以这行也给列了出来

 

3:排除掉字符

[0-5]匹配出0~5这6个数字,而[^0-5]就会排除这0个数字,也就是匹配6~9,比如还是上面的例子:

[lihui@localhost ~]# egrep ' [^0-6][0-9];' /usr/local/nginx/conf/nginx.conf
		listen       80;

前面匹配7~9,所以上面一行60无法匹配到,只能匹配到80

 

4:任选表达式

符号 | 的意思就是或,它能够将不同的子表达式合成一个表达式,而这个合起来的表达式可以匹配任意一个子表达式,也就是‘hello | world’匹配hello和world其中一个就行了,还是上面例子:

[lihui@localhost ~]# egrep '60|80' /usr/local/nginx/conf/nginx.conf
		keepalive_timeout 60;
		listen       80;

或者这么写更犀利

[lihui@localhost ~]# egrep '(6|8)0' /usr/local/nginx/conf/nginx.conf
		keepalive_timeout 60;
		listen       80;

但是这里的括号不能丢掉,否则意思就变成了匹配6或者80的行了

[lihui@localhost ~]# egrep '6|80' /usr/local/nginx/conf/nginx.conf
		keepalive_timeout 60;
		fastcgi_buffer_size 64k;
		fastcgi_buffers 4 64k;
		fastcgi_temp_file_write_size 256k;
		gzip_buffers     4 16k;
		gzip_disable        "MSIE [1-6]\.";
		listen       80;

 

5:区分大小写

上面匹配出端口的时候,匹配的是listen,假如有些配置文件,你并不清楚listen到底是大写还是小写,需要忽略大小写,要么你就两种都匹配以下,要么就通过-i来忽略

[lihui@localhost ~]# egrep 'LISTEN' /usr/local/nginx/conf/nginx.conf
[lihui@localhost ~]# egrep -i 'LISTEN' /usr/local/nginx/conf/nginx.conf
		listen       80;

 

6:单词分界符

单词分界符\<和\>是为了区分单独的单词和一个更长的单词中包含我们要的单词,比如我们想要的是单独的like,而不是unlikely,比如先查看下开关为on的行:

[lihui@localhost ~]# grep 'on' /usr/local/nginx/conf/nginx.conf
		worker_connections 51200;
		default_type  application/octet-stream;
		sendfile on;
		tcp_nopush     on;
		tcp_nodelay on;
		fastcgi_connect_timeout 300;
		gzip on;
		gzip_http_version 1.0;
		gzip_types       text/plain application/x-javascript text/css application/xml;
		gzip_vary on;
		#limit_zone  crawler  $binary_remote_addr  10m;
		location ~ .*\.(php|php5)?$
				include fcgi.conf;
		location /status {
			stub_status on;
		location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
		location ~ .*\.(js|css)?$

显然有很多行不是我们要的,我们需要的on是一个单独的开关

[lihui@localhost ~]# grep '\<on\>' /usr/local/nginx/conf/nginx.conf
		sendfile on;
		tcp_nopush     on;
		tcp_nodelay on;
		gzip on;
		gzip_vary on;
			stub_status on;

 

7:可选项

可选项就是某项是可选的,也就是这项存在与否都能够匹配到,通过符号?来实现,看下面例子

[lihui@localhost ~]# egrep '60|80' /usr/local/nginx/conf/nginx.conf
		keepalive_timeout 60;
		listen       80;
[lihui@localhost ~]# egrep '60|80?' /usr/local/nginx/conf/nginx.conf
		server_names_hash_bucket_size 128;
		keepalive_timeout 60;
		fastcgi_busy_buffers_size 128k;
		listen       80;

显然80后面加了一个?,那么8后面的0就变成可选项,也就是存在或者去掉都能匹配,因此加上0匹配到了80,而去掉0还能匹配上128的另两行

 

8:括号反向应用

在perl,python里,括号都能匹配出我们想要的结果,同理,通过括号指定的内容,可以通过\1,\2,\3来代替,如下:

[lihui@localhost ~]# egrep 'fastcgi_(index) \1.php' /usr/local/nginx/conf/nginx.conf
				fastcgi_index index.php;

这里的\1代替的就是index

 

9:转义

假如我们需要匹配的字符在正则表达式里本身就有特殊含义,比如想直接通过(js|css)?$来匹配出这一行,可千万别:

[lihui@localhost ~]# egrep '(js|css)?$' /usr/local/nginx/conf/nginx.conf
........整个文件内容........

原因是?是可选项,所以当作不存在的时候,匹配所有行,因此输出了所有内容,假如正则表达式一定要带上(js|css)?$,就必须将特殊符号转义,也就是失去他们正则表达式里的效果,用符号\

[lihui@localhost ~]# egrep '\(js\|css\)\?\$' /usr/local/nginx/conf/nginx.conf
		location ~ .*\.(js|css)?$

这样就OK了

 

正则表达式在所有脚本语言里或者有些差别,但是思想没差异

发表回复