正则表达式–学习笔记
正则表达式,是一种对字符串操作的逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。—-真真是个好东西
But , 那些规则真的不好记住,稍微要实现点复杂功能,就得翻箱倒柜找笔记,找度娘,很费时间。。。
废话真多,开始正题!
1 常用符号
- ^ 匹配输入字符串的开始位置
- + 匹配一个或多个字符(至少要有一个)
- $ 匹配输入字符串的结束位置
- * 匹配0个或多个字符串(可以没有,也可以有)
- ? 最多出现一次
- \ 转义
- . 除换行之外的任何字符
- | 指明两项之间选择一项
/^c/ => 匹配'c'开头的字符串
/^cm+/ => 匹配'cm'开头的字符串
/^cm+k$/ => 匹配'cmk','cmmmmk'中间不能有其他字符
/^cm+a+b*k$/ => 匹配'cmak', 'cmmmaaak', 'cmmmaaaabbbbk'等
/^cma?k$/ => 匹配'cmak'或'cmk'
/^cm\\+k$/ => 匹配'cm\k','cm\\\k'等
/^cm.*k$/ => 匹配'cm'开头,'k'结尾的字符串
/^cm|hk$/ => 匹配'cmk','chk'
2 转义字符
- \f 匹配一个换页符
- \n 匹配换行符
- \r 匹配回车符
- \s 匹配任何空白字符,如空格,制表符,换页符等
- \S 匹配任何非空白字符
- \t 匹配制表符
- \v 匹配垂直制表符
- \d 匹配数字
- \D 匹配非数字
- \w 匹配下划线在内的任何单词字符:_ A-Z a-z 0-9
- \b 匹配字符边界,字符与空格之间的位置
/\b[\w]+\b/ // 匹配出一个单词
3 表达式
- [ ] 中括号表达式,字符集
/^c[0-9]+k$/ =>匹配'c'开头,'k'结尾,中间至少有一个数字的字符串
/^c[0-9A-Z]+k$/ =>匹配'c'开头,'k'结尾,中间至少有一个数字或大写字母的字符串
/^c[0-9A-Za-z_]+k$/ => 等价于 /^c\w+k$/
/^c[^0-9]+k$/ => 中括号内的^表示除此集合之外的字符
- {} 限定出现次数
/^[0-9]{6}$/ => 匹配6位数字
/^[0-9]{4,6}$/ => 匹配4到6位数字
- () 子表达式,可以看成一个字符,具体后面讲
4 示例解析
/^(-|\+)?[1-9][0-9]*(\.[0-9]{1,6})?$/
// 匹配可带正负号的实数(+-1.0之间的小数无法匹配,尴尬)
// (-|\+) 表示匹配'-'或者'+',由于'+'具有特定含义,需要转义
// ()? 表示括号内匹配的内容最多出现一次
// [1-9][0-9]* 表示匹配1-9打头的多位数字
// \.[0-9]{1,6} 表示匹配1到6位小数部分,'.'需要转义
// 这个表达式可以匹配可带正负号,最多6位小数的实数,但是不能匹配出±1.0之间的小数,略显尴尬,主要原因是这里强制要求数字首位必须是1-9,这样做的原因不匹配这样的数字: 000123.56
// 为了解决这个问题,可以加个选择条件([1-9][0-9]*)|0, 开头可以有一个0
/^(-|\+)?(([1-9][0-9]*)|0)(\.[0-9]{1,6})?$/ // 完美解决了
5 捕获组
捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用。
5.1 普通捕获组:(expression)
- 编号规则:按照’(‘编号出现的顺序,从左到右,从1开始编号
(\d{4})-(\d{2}-(\d\d))
// 捕获组1:\d{4}
// 捕获组2:\d{2}-(\d\d)
// 捕获组3:\d\d
5.2 命名捕获组:(?\expression)
- 编号规则:可按name引用,也可按编号引用,编号规则也是按’(‘出现的顺序开始编号
当两者混用时,先给普通捕获组编号,再给命名捕获组编号
(\d{4})-(?<date>\d{2}-(\d\d))
// 捕获组1:\d{4}
// 捕获组2:\d\d
// 捕获组3:(?<date>\d{2}-(\d\d))
6 反向引用
捕获组捕获到的内容在正则表达式内部进行引用,则为反向引用- 通过编号引用: \number, 如 \1, \2
- 通过命名引用: \k\
/(ab)\1/ // 匹配'abab', \1表示(ab)匹配到的内容
/(ab)\1{2}/ // 匹配'ababab', \1表示(ab)匹配到的内容
7 正向预查
正向匹配: (?=pattern)
正向不匹配: (?!pattern)’
/\b[\w]+(?=ing\b)/
// 匹配的字符串满足'\b[\w]+',而且后面需要跟ing
// 符合此规则的字符串有:coming,going,但comingx 不符合
8 正则表达式用法
正则表达式最基本的用法有验证字符串是否合法和提取子字符串
应用场景1:验证表单—验证邮箱是否合法
/^\w+@\w+\.\w+$/ // 匹配**@**.**这种类型
应用场景2:提取html中img元素的src和name的值
示例字符串:
<img alt="" border="0" name="g6-o44-1" onload="DrawImage" src="/bmp/foo1.jpg" />
表达式:
/<img\b(?=(?:(?!name=).)*name=(['"]?)([^'"\s>]+)\1)(?:(?!src=).)*src=(['"]?)([^'"\s>]+)\3[^>]*>/i
// 捕获组里面\2 和 \4分别为name和src的值
上述表达式如何理解呢?
- 首先,先把正向预查删了,更好理解,如下:
/<img\b(?:(?!src=).)*src=(['"]?)([^'"\s>]+)\3[^>]*>/i
- (?:(?!src=).)* 这个表示不包含子串’src=’和’\n’的任意字符
- ([‘”]?)([^’”\s>]+)\3 中,\3 表示的就是([‘”]?)匹配的结果,组合起来就是’**’,”**”或**,那么中间的就是匹配src的值了,([^’”\s>]+), 排除掉了’,”,空白字符以及’>’,这样就顺利把src的值取到了。
- 那怎么取name的值呢,因为name和src的相对位置可能不同,所以不知直接套用取src的方法了,这里采用了正向预查的方法,其实也跟取src的值原理一样,不过是放在预查里面
(?=(?:(?!name=).)*name=(['"]?)([^'"\s>]+)\1)
9 修饰符
- i 表示不区分大小写
- g 全局搜索(查找所有匹配而非在找到第一个匹配后停止)
- m 多行匹配
10 Javascript中正则表达式的应用
10.1 RegExp对象
表示正则表达式,它是对字符串执行模式匹配的强大工具。
- 方法:test() 用于检测字符串是否匹配该表达式,匹配成功则返回true
- 方法:exec() 用于检索字符串中的正则表达式的匹配
- 属性:$n n表示1-99,取捕获组的值
var patt = /<img\b(?=(?:(?!name=).)*name=(['"]?)([^'"\s>]+)\1)(?:(?!src=).)*src=(['"]?)([^'"\s>]+)\3[^>]*>/i;
var str = '<img alt="" border="0" name="g6-o44-1" onload="DrawImage" src="/bmp/foo1.jpg" />';
var result patt.test(str);
if (result) {
console.log(RegExp.$2); // g6-o44-1
console.log(RegExp.$4); // /bmp/foo1.jpg
}
var res = patt.exec(str);
console.log(res[0]); // 匹配出的字符串
console.log(res[1]); // RegExp.$1
console.log(res[2]); // RegExp.$2
console.log(res[3]);
console.log(res[4]);
console.log(res.index); //开始匹配的地方
console.log(res.input); //输入字符串
10.2 字符串对象对正则表达式的支持
- search()
- replace()
- match(), 等同于RegExp的exec方法
- split(), 分割字符串,分隔符可用正则表达式