完整的正则表达式是由很多小的模块组成的,而每个小的模块都很简单,但是这些符号如果是随意结合的话,可以有无穷无尽的组合
正则表达式除了信手拈来的\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了
正则表达式在所有脚本语言里或者有些差别,但是思想没差异