正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。
导语
简单来说,正则表达式做两个事:
- 匹配
- 替换
在无论代码生涯,还是正常生活当中,会遇到很多情况:
- 从html文本中获取某些信息
- 表单内容验证
- 代码批量更改名字
- vim中查找内容
- 一堆杂乱的日志文档中找出重要信息
- 等等
其实写代码即操作文本,正则表达式是操作文本能手,如果灵活运用自如,如虎添翼。本片文章主要说正则表达式 - 是什么、为什么、怎么样
语法一览
字符 | 描述 |
---|---|
^ | 在单行模式中匹配文本最前面的位置 , 在多行模式中匹配每一行的行首 |
$ | 在单行模式中匹配文本最后面的位置 , 在多行模式中匹配每一行的行尾 |
+ | 匹配1个以上 , 例如a+就是匹配 a、aaa 、aaaaa |
? | 匹配0个或1个 , 例如ab?就是匹配 a 、ab |
* | 匹配0个以上 , 例如ab*就是匹配 a 、ab 、abb 、abbbb |
{n} | 匹配n个,例如ab{3}就是匹配 abbb |
{n,} | 匹配n个以上,例如ab{3,}就是匹配 abbb 、abbbbb |
{n,m} | 匹配n到m之间,例如ab{3,5}就是匹配 abbb 、abbbb 、abbbbb |
\\ | 转义符,将特殊字符变成普通字符看待 ,例如 \\\\+ 表示匹配字符+ |
. | 匹配非'\\n'外的任意字符 |
\\d | 匹配一个数字 |
\\D | 匹配一个非数字 |
\\s | 匹配一个空格 |
\\S | 匹配一个非空格 |
\\n | 匹配一个换行符 |
\\t | 匹配一个制表符 |
\\t | 匹配一个制表符 |
\\w | 匹配一个包含下划线在内的单词或字符,相当于[a-zA-Z0-9],例如 world_one |
\\W | 匹配一个包含下划线在内的非单词 |
a\\b | ’或‘ 语法 ,匹配 a 或者 b ,该处是竖线 |
[xyz] | 匹配括号内包含的任意一个字符 |
[^xyz] | 匹配括号内未包含的任意一个字符 |
[a-z] | 匹配括号未包含的范围字符,该例匹配a~z任意一个字符 |
[^a-z] | 匹配括号内未包含的范围字符 |
(pattern) | 把匹配内容放到分组中 |
(?:pattern) | 匹配,但不放到分组中 |
(?=pattern) | 零宽断言 , 断言前方是pattern |
(?!pattern) | 零宽断言 , 断言前方不是pattern |
(?<=pattern) | 零宽断言 , 断言后方是pattern |
(?<!pattern) | 零宽断言 , 断言后方不是pattern |
细细道来
如需灵活运用正则表达式,必须熟悉大部分元字符的含义,并且运用于实际当中,然后多产出正则。
在正则表达式中有几个要点:
匹配一个字符
匹配一个字符,有很多种方法,可以直接使用字符本身a、b、c、d,也可以使用通配符\\w、\\S、[a-z] , 在实际情况中灵活选择。
例如:a123bb456
-
正则可以是 “ a\\d{3}bb\\d{3} ” , 可以理解为:“匹配a字符,接着匹配3个数字,接着匹配b字符,接着匹配b字符,最后匹配3个数字”
-
正则可以是 “ [a-z\\d]{9} ” , 可以理解为:“匹配9个( a到z 或者 数字 )”
-
正则可以是 “ \\S{9} ” , 可以理解为:“匹配9个非空字符”
没有唯一的正则表达式,只有适合解决需求的正则表达式
在写正则表达式中根据需求,思考使用的通配符是否对结果有影响,如无影响,都可以使用
转义
例如需要匹配'['字符,因为'['在正则表达式中有其意义,所以可以使用\\[来匹配,就是在前面加反斜杠\\
重复匹配
重复在正则中也是最常用的通配符之一。
例如
12345
正则是:\\d{5} 代表 “匹配5个数字“
或者是:\\d+ 代表 “匹配至少1个数字,贪婪模式”
或者是:\\d* 代表 “匹配至少0个数字,贪婪模式”
或者是:\\d+?\\d{4} 代表 “匹配至少1个数字,懒惰模式,再匹配4个数字”
或者是:\\d*?\\d{5} 代表 “匹配至少0个数字,懒惰模式,再匹配5个数字”
这里有一个概念
- 贪婪模式 : 是有多少匹配多少
- 懒惰模式 : 尽量少地匹配
例如现在要匹配一个img标签
\\\\< img src="http://www.baidu.img/50B2" style="height:75px;">
正则 :
<\\\\simg\\\\ssrc="[^"]+"[^>]*>
该处久用了贪婪模式,匹配到[^"]+
的时候表示 1个以上非“的字符,所以,会匹配到50B2,因为再下去就是“了,所以贪婪也就贪婪到这里了。
如果把正则换成 <\\\\simg\\\\ssrc="[^"]+?"[^>]*>
,该处久用了懒惰模式,在匹配到[^"]+?
的时候,匹配内容为:<img src="h ,因为使用了?,用的是懒惰模式,所以,只匹配到1个字符,然后在匹配“,因为不是”,所以匹配终止,匹配不到任何内容。
这个特性在正则中大有用处,细细理解!凡事用到了重复匹配,都可以使用?来进行懒惰的控制,默认是贪婪模式
零宽断言
相信对于很多初学者来说,看到断言开始都会一头雾水,下面详细说明,如何使用?
零宽断言就是下结论,例如ab,正则:a(?=b),匹配a并且向右看是b,得到的结果是a,断言不会在匹配的内容当中,如果是a(?=c),则匹配不到任何内容,因为匹配a以后向右看并不是c
如果上面的例子理解了,那么对于零宽断言就差不多了,只是看的方向不一样。
- (?=pattern) 向右看是
- (?!pattern) 向右看不是
- (?<=pattern) 向左看是 (JS不支持)
- (?<!pattern) 向左看不是 (JS不支持)
例子:abc
(?<=a)b(?=c) : 匹配b,并且向左看是a,向右看是c
(?<!b)b(?!b) : 匹配b,并且向左看不是b,向右看不是b
分组
分组是用于在匹配过程中,将需要的有用信息提取出来,方便使用。
分组的通配符是括号,就是需要提取信息的地方加括号括起来
例如还是要匹配一个img标签 ,但是我需要提取出其中的url
\\\\< img src="http://www.baidu.img/50B2" style="height:75px;">
可以看到,其中分组1中的内容就是我们需要的url,当然可以使用多个括号进行多个分组的抽取
程序中如何获取?下面给出js中的demo
var content = '![](http://www.baidu.img/50B2)'
var regex = /<img\\\\ssrc="([^"]+)/
var url = content.match(regex)[1]
选项
最后说一下选项,同一正则表达式不同的选项可能回产生不同的效果。
名称 | 选项 | 说明 |
---|---|---|
IgnoreCase | i | 忽略大小写 |
Multiline | m | 多行模式 |
global | g | 全局匹配 |
忽略大小写大家应该都清楚,多行模式的话就会影响和$的匹配,在单行模式中匹配内容的首位,在多行模式中^匹配每一行的首位,$同理。
全局匹配的话就是匹配所有,如果不开全局匹配,则如匹配成功,则退出,结果只有一个。
推荐 ( 绝对没拿回扣~)
- 书
《精通正则表达式》
《正则表达式经典实例》 - 在线测试工具
传送门
总结
多想,多写,多运用,当对正则表达式灵活运用的时候,你会有一种翱翔天际的感觉。
如有错误指出,望各位指出,谢谢xie x
请作者喝茶:
Geek必备 - 正则表达式
网友评论