【怕啥弄啥系列】总要爱上它《正则》 - 高级

2019-08-02 14:41:52 浏览数 (1)

现在开始写 高级篇,话不多说,开始表演

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)

0 人点赞