零散专题02 正则表达式
正则表达式学习笔记。
[TOC]
元操作符
操作符 | 含义 |
---|---|
. |
除换行符(\n )之外的任意字符 |
\w |
匹配字母、下划线、数字、汉字 |
\s |
匹配任意空白字符 |
\d |
任意数字 |
^ |
匹配字符串开始 |
$ |
匹配字符串结束 |
\b |
单词分界处(单词的开头或结尾),用于限定单词范围 |
` | ` |
[] |
字符集,不关心顺序,使用- 指定范围 |
反义操作符
与某些元字符匹配相反的内容
操作符 | 含义 |
---|---|
\W |
匹配字母、下划线、数字、汉字之外的任意字符 |
\S |
匹配任意非空白字符 |
\D |
任意非数字字符 |
\B |
匹配不是单词开头或者结尾的位置 |
[^abc] |
匹配字符集之外的字符 |
重复限定符
操作符 | 含义 |
---|---|
* |
重复零次或更多次 |
? |
重复零次或一次 |
+ |
重复一次或更多次 |
{n} |
重复n 次 |
{n,} |
重复n 次或更多次 |
{n,m} |
重复n 次至m 次 |
分组
分组匹配
重复限定符值限制它左边最近的一个字符,如果需要匹配多个字符,就需要使用()
来将括号中的内容作为一个整体。
例如,要匹配含有多个ab
时:
1 | ^(ab)* |
捕获组
使用()
来进行匹配时,()
中的内容会保存到内存中用数字或者显示命名的组里,以深度优先进行编号,后面可以通过序号或者名称来使用匹配的结果
捕获组存在的前提是整项已匹配
数字编号捕获组
捕获组默认使用数字编号。例如,有这样一个表达式:
1 | (\d)(\d) |
当用它来匹配12
时,会有是三个分组:
12
,整个表达式本身1
,第一个捕获组2
,第二个捕获组
在JavaScript的replace
方法的第二个参数中,就可以使用$1
来访问第一个捕获组
命名编号捕获组
语法:(?<name>exp)
作用:人为为捕获组添加名称,例如:
1 | (?<a>\d)(?<b>\d) |
上面的表达式,在replace
方法中除了用$1
来访问第一个捕获组外,还可以使用$<a>
来访问
非捕获组
语法:(?:exp)
作用:与捕获组相反,如果指向进行分组匹配,而不需要保存到捕获分组中,就需要使用非捕获组
反向引用
匹配到捕获组后,会保存到内存中,不仅可以在外部引用,也可以在正则表达式内部进行引用,这就是反向引用(也叫后向引用)
反向引用会大大增加捕获组的能力,因为反向引用,引用的是匹配子表达式的内容,注意,不是子表达式本身,而是内容。这个内容可以用来查找一些重复的内容或者进行字符替换
引用的方式是在正则表达式内部使用\1
来引用第一个捕获组,\2
引用第二个捕获组,以此类推,\0
对应的是整个正则表示
举个例子
举个例子,要查找'aabbbbgbddesddfiid'
里面成对的字母
1 | const str = 'aabbbbgbddesddfiid'; |
字节跳动的面试题
一个在字节跳动的面试题,找出一个字符串中出现次数最多的字符,当时脑子抽,非要计算出每个字符出现的次数,存起来,然后取最大的
实际上使用反向引用根本就没有这么麻烦,使用match
方法得到同一个字符串为一项组成的数组(就和上面的例子一样),然后按照树组成员的length
排序即可
1 | const str = 'asdfaaaa'; |
零宽断言
零宽断言是为了判断一个位置,这个位置满足正则表达式的匹配,它不占字符,只匹配位置。零宽断言分为以下几种:
- 正向先行断言
- 正向后行断言
- 负向先行断言
- 负向后行断言
里面的正、负向指的是与匹配正则表达式还是非匹配的区别,先行、后行的区别是匹配前面(右侧)还是后面(左侧)的内容
正向先行断言
语法:(?=pattern)
作用:匹配pattern
表达式前面的内容,返回这个位置。也就是说,此位置右侧的字符能满足pattern
时条件为真,匹配此位置左侧的字符
举个例子,有这样一段HTML代码:
1 | '<span class="read-count">阅读数:641</span>'' |
我们希望匹配出641
,就可以使用正向先行断言,641
前面的字符是</span>
,匹配出这个位置即可:
1 | const str = '<span class="read-count">阅读数:641</span>'; |
正向后行断言
语法:(?<=pattern)
作用:与正向先行断言的区别就是,匹配的是后面(即左侧)的内容满足表达式要求的位置。
使用正向后行断言,也可以完成上面的例子
1 | const str = '<span class="read-count">阅读数:641</span>'; |
负向先行断言
语法:(?!pattern)
作用:匹配非pattern
表达式前面的内容,返回这个位置。
举个例子,要匹配出我爱祖国,我是祖国的花朵
中不是的花朵
前面的祖国,正则可以这样写:
1 | 祖国(?!的花朵) |
负向后行断言
语法:(?<!pattern)
作用:匹配非pattern
表达式后面的内容,返回这个位置。
3 下面的表达式表示的意义任意2-8位数字,^表示后面的内容是字符串的开始,$表示前面的内容是字符串的结束
1 | ^\d{2,8}$ |
贪婪匹配和非贪婪匹配
贪婪匹配
当正则表达式中包含重复限定符时,在整个表达式得到匹配的前提下,匹配尽可能多的字符,这种匹配方式叫做贪婪匹配
默认的限定符都是贪婪匹配的。
当多个量词同时出现时,如果能满足各自最大程度的匹配,就会互不干扰。如果不能满足,会根据深度优先原则,也就是从左到右的每个贪婪量词,优先最大数量的满足,剩余的再分配给下一个量词匹配
非贪婪匹配
与贪婪匹配相反的就是非贪婪匹配,它在满足整个表达式满足匹配的前提下,匹配尽可能少的字符。
贪婪量词是在普通的贪婪量词后面加上?
,例如*?
、+?
、??
、{n,m}?
操作符 | 含义 |
---|---|
*? |
匹配字母、下划线、数字、汉字之外的任意字符 |
\S |
匹配任意非空白字符 |
\D |
任意非数字字符 |
\B |
匹配不是单词开头或者结尾的位置 |
[^abc] |
匹配字符集之外的字符 |
JS中的正则表达式
JS中表达式,默认区分大小写,找到第一个匹配项就结束,单行寻找:
1 | const reg = /pattern/ |
- 在
/pattern/
后面添加标识符g
,表示全局模式,应用于所有字符串 - 加标识符
i
,表示不区分大小写 - 加标识符
m
,表示多行模式,继续寻找下一行
JS常用的正则表达式的几个方式有replace
、test
、exec
、match
,详细的介绍可以参考这篇笔记《JS46 JS中的match和exec方法》
实例
正则验证空格
1 | const reg = /\s/; |
去除空格
1 | const reg = /\s/g; |