现在开始写 高级篇,话不多说,开始表演
1
贪婪匹配、惰性匹配
正则默认是贪婪匹配的,为什么一开始设计默认是贪婪呢?我估计,是设计者想设计得人性化一些
1
贪婪匹配
当使用 量词 的时候 ,默认都是贪婪匹配,匹配得越长越好
一个短的匹配项 是合规的,一个长的匹配项也是合规的,那么贪婪匹配会选择长的
量词都有哪些?
参考我的上一篇基础篇
【怕啥弄啥系列】总要爱上它《正则》 - 基础
2
惰性匹配
一个短的匹配项 是合规的,一个长的匹配项也是合规的,那么惰性匹配会选择短的
当我们在量词的后面加上一个 ? ,那么就是 惰性匹配
3
统一举例对比
1、使用符号量词
| 1 | 更多 |
---|---|
* | 0 | 更多 |
? | 0 | 1 |
贪婪匹配
代码语言:javascript复制"<>>".match(/<(.*)>/g)
"<>>".match(/<(.?)>/g)
"<>>".match(/<(. )>/g)
清一色越多越好,没有哄你的
惰性匹配,在 量词 后面加上 ?
代码语言:javascript复制"<>>".match(/<(.*?)>/g)
"<>>".match(/<(.??)>/g)
"<>>".match(/<(. ?)>/g)
看到了吧,就变成匹配更少的了
2、数字量词
虽然给定了区间 ,默认也是尽可能以最大的区间值进行匹配
代码语言:javascript复制"<>b>".match(/<(.{1,})>/g)
"<>b>".match(/<(.{1,3})>/g)
<>b> 和 <> 都是合规的,但是 贪婪匹配 只会匹配更长的
试下惰性匹配,加上 ?
代码语言:javascript复制"<>b>".match(/<(.{1,}?)>/g)
"<>b>".match(/<(.{1,3}?)>/g)
<>b> 和 <> 都是合规的,但是惰性匹配只会匹配更短的
2
分组、捕获
1
分组
在 正则表达式中加入 小括号 表示分组
像是这样
代码语言:javascript复制/(d)/.exec("adg")
2
捕获
正则 的 括号部分 的匹配项,独立捕获出来
捕获这个动作,一般配合 正则 的 exec 方法
举栗子
比如下面,想把1 和 3 之间的数字捕获出来,中间就要加上括号
你看到了,返回的数组中,有几项内容
第一项,匹配项,是123,对应 1(d)3
第二项,捕获分组,是 2,对应 (d)
第三项,匹配的起始位置,123在字符串中的起始位置是1
第四项,匹配的源字符串,a123
3
捕获 型分组
加了括号,就叫捕获型分组。而且匹配时会把每个分组给保存起来
TIP:可以同时捕获很多个,只要你加了 多个括号
4
非捕获型分组
加了括号,但是不捕获,就叫 非捕获分组
比如,我 加括号是为了使用 分隔符表示或者 的意思
代码语言:javascript复制/w(2|3)/.exec("ab2 ab3")
这里为了表示 匹配 2 或者 3,但是你却把他捕获出来了,我不想要啊
怎么办!
这时候就用到 非捕获型分组
敲黑板,重点来了,看这里 ?:
没错,你看到的就是 非捕获分组的重点,记下来,要考!
怎么用!
把 ?: 放在正则 括号内的开头 就可以了
举栗子
哈哈,you 就不会被捕获出来啦
想使用括号,但是不想捕获,就用 非捕获型分组
3
引用、反向引用
这两个东西,是属于 捕获型分组 的内容,只有在捕获型分组中才存在 引用和 反向引用
1
引用
引用的意思,按我的理解就是引用捕获到的分组
1、Regexp对象 获取 引用
Regexp对象 会保存 最近的捕获的分组
所以在 Regexp 上可以获取到 最近的捕获的分组
举栗子
每次捕获一次,RegExp 就会 替换保存 最新的捕获分组
RegExp 的 $1 - $9 都可以保存分组,也就是可以保存 9 个分组
打印一下 RegExp 这个函数对象
Tip
使用 console.dir 打印 RegExp,因为它是个函数对象,直接 log 打印,会看不到它的属性
2、 replace 使用 引用
同样是使用 $1 -$9 的形式去引用捕获分组,然后把它放在第二个参数中
replace 使用 引用,我一般用来匹配那些 不确定是否存在 的 的向
举栗子
比如 这样的字符串
<p>111</p><a>222</a><b>333</b>
我要把所有的标签都改成 p 标签,我需要匹配标签,首标签不存在 /, 而尾标签存在 /,我替换时不确定 / 是否存在,所以我需要去把 / 放入分组进行捕获
如果匹配到,那么是尾标签,替换时就要 / ,如果没有匹配到,是首标签,替换时不用 /
代码语言:javascript复制"<p>111</p><a>222</a><b>333</b>".replace(/<(/?)w>/g,"<$1p>")
$1 标签 表示 是否存在 / 这个匹配分组
a、如果存在 / ,<$1p> 变成 </p>
b、如果不存在 / ,<$1p> 变成 <p>
这样就能同时匹配 首尾两种标签了
2
反向引用
在 正则表达式中 引用分组,减少写重复的代码,相当于使用一个变量
用法注意事项
1、必须要使用分组
2、转义 数字 表示引用第几个分组
1、必须要使用分组
就是正则中必须有括号喽
代码语言:javascript复制/(w)/
2、转义 数字 表示引用 正则 中的第几个分组
代码语言:javascript复制/(w)(d)12/
那么 (w) 是第一个分组,(d) 是第二个分组
1 表示 引用第一个分组,2 表示引用第二个分组,而 数字需要转义,所以加上
上面的正则,意思是先匹配到 AB,然后使用 AB 这两个分组,去匹配 ABAB
通常我会使用它,进行匹配 头尾相同 的内容
举栗子
比如下面的字符串
<p>111</p><a>222</a><b>333</b>
如果我想匹配 出 <p>111</p> 、<a>222</a> 这样,但是我怎么控制首尾标签的名字一样呢?
反向引用,在这里就起作用了
代码语言:javascript复制"<p>33</p> <a>11</a> <div>11</div>".match(/<(w)>. </1>/g)
这样,就能保证首尾标签一样了
最好配合 惰性匹配 使用,否则 匹配的 p 标签 就会包含很多个
这样,加上 ?进行惰性匹配,就是正确的了
4
正向前瞻,反向前瞻
前瞻的用法,类似于排除过滤的功能,只要 后面 有什么 或者 没有什么 的内容
1
正向前瞻
简单说
就是匹配 后面跟着某些内容 的 字符串
我要匹配一个东西,他后面必须跟着某个东西!
常用于排除过滤功能
重点符号 ?=
TIP
1、把 这个符号放在 需要跟着的内容 的前面
2、需要使用小括号把最外层包起来
举栗子
这样说,现在有一串字符串
"I coding, I eat, I smile" , 我只想拿到I I coding 这一段,就是我要 后面有 coding 的 I
那么使用正向前瞻做法就是
代码语言:javascript复制'I coding,I eat,I smile'.match(/hoho(?=scoding)/g)
2
反向前瞻
简单说
反向前瞻,匹配 后面不跟着某些内容 的 字符串
我要匹配一个东西,他后面不能跟着某个东西!
重点符号 ?!
TIP
1、把 这个符号放在 不需要跟着的内容 的前面
2、需要使用小括号把最外层包起来
举栗子
这样说,现在有一串字符串
"I coding, I eat, I smile" , 我不想拿到I I coding 这一段,就是我要 后面没有 coding 的 I
额.....又是一样的例子
使用反向前瞻做法就是
代码语言:javascript复制'I coding,I eat,I smile'.match(/hoho(?=scoding)/g)