一、认识正则表达式
文章目录
1.什么是正则表达式?
正则表达式(Regular Expression),又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合, 组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
2.为什么要学习正则表达式?
通过使用正则表达式,可以:
- 测试字符串内的模式。 例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。
- 替换文本。可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
- 基于模式匹配从字符串中提取子字符串。 可以查找文档内或输入域内特定的文本。
二、正则表达式常用匹配规则
语法 | 说明 |
---|---|
+ | 表示匹配一个或多个 |
* | 表示匹配0个或多个 |
? | 表示匹配0个或1个 |
[ABC] | 表示匹配[…] 中出现的所有字符 |
[^ABC] | 表示匹配[…] 中以外的所有字符 |
[a-z] | 表示匹配所有小写字母 |
[A-Z] | 表示匹配所有大写字母 |
\w | 表示匹配数字、字母、下划线 |
\W | 表示匹配非数字、字母、下划线的任何字符 |
\s | 表示匹配任何空白字符,包括空格、制表符、换页符等等 |
\S | 表示匹配任何非空白字符 |
\d | 表示匹配数字 |
\D | 表示匹配除了数字以外任意字符 |
[\w\W] | 表示匹配任意字符 |
[\s\S] | 表示匹配任意字符 |
[\d\D] | 表示匹配任意字符 |
. | 表示匹配除换行符 \n 之外的任何单字符 |
^ | 匹配输入字符串的开始位置 |
$ | 匹配输入字符串的结尾位置 |
{n} | n 是一个非负整数。匹配确定的 n 次 |
{n,} | n 是一个非负整数。至少匹配n 次 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次 |
(x|y) | 查找任何以x、y分隔的选项 |
注意:正则表达式从左到右进行计算,并遵循优先级顺序,相同优先级的从左到右进行运算,不同优先级的运算先高后低。其优先级顺序如下:转义符>圆括号和方括号>限定符>元字符>替换操作. |
三、正则表达式的语法
/pattern/flags
/正则表达式主体/修饰符(可选)
其中,常用修饰符如下:
- i 执行对大小写不敏感的匹配。
- g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
- m 执行多行匹配。
- s 执行特殊字符圆点 . 中包含换行符的匹配。
- y 执行高效匹配,只要下一个字符不满足匹配条件,就会停止匹配。
四、使用正则表达式
1.使用字符串的方法
- search() 方法:用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置。var n = str.search(regexp),search方法可使用字符串作为参数,字符串参数会转换为正则表达式。
- replace() 方法:用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串,并返回替换后的新字符串。var txt = str.replace(regexp,“text”),replace方法可使用字符串作为参数,字符串参数会转换为正则表达式。
- match() 方法:检索与正则表达式相匹配的子字符串,它是一次匹配,只要找到了一个匹配的结果就会返回, 而不是查找所有匹配的结果。 str.match(regexp),该方法也可使用字符串作为参数,字符串参数会转换为正则表达式。
- matchAll() 方法:ES11的新特性,matchAll() 方法返回一个包含所有匹配正则表达式的结果的迭代器。可以使用 for…of 遍历,或者使用 展开运算符(…) 或者 Array.from 转换为数组。str.matchAll(regexp),如果所传参数不是一个正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp。如果RegExp对象没有/g标志,则将引发TypeError 。
- split() 方法:把字符串分割为字符串数组,返回值为分割后数组。使用示例:str.split(regexp)。
2.使用RegExp 对象
- test() 方法:test()方法搜索字符串指定的值,根据结果并返回真或假。
- exec() 方法:exec()方法检索字符串中的指定值。返回值是被找到的值。如果没有发现匹配,则返回 null。使用exec方法时RegExp 对象的lastIndex属性会保留上次检索到的位置,下次使用exec()方法检索时从该位置开始,若没有检索到则为空。
3.exec()全局匹配与实现matchAll()匹配
let str = "abcbbabcabc";
let reg = new RegExp(/abc/ig);
// exec全局搜索
let result = [];
while(res = reg.exec(str)){
console.log(reg.lastIndex);
result.push(res);
}
console.log(result);
// matchAll全局搜索
String.prototype.matchAll = function(reg){
let res = this.match(reg);
if(res){
let str = this.replace(res[0],"^".repeat(res[0].length));
let match = str.matchAll(reg)||[];
return [res,...match];
}
}
let matches = str.matchAll(/abc/i);
for (const it of matches) {
console.log(it);
}
五、贪婪匹配与惰性匹配
贪婪匹配——在匹配成功的前提下,尽可能多的去匹配
惰性匹配——在匹配成功的前提下,尽可能少的去匹配
注意:默认的贪婪匹配是从后往前最大长度的匹配,惰性匹配就是在贪婪量词后面加个?从字符串的前面开始匹配,最小长度的匹配
示例:
let str = "abbaabbxyabbx"
let reg1 = /.*bb/ig
let reg2 = /.*?bb/ig
console.log(str.match(reg1));//["abbaabbxyabb"]
console.log(str.match(reg2))//["abb", "aabb", "xyabb"]
六、断言匹配
正则表达式中,用于查找某些内容之前或者之后的东西,叫做断言。
- (?=pattern) :要求当前位置开始向后的字符串能匹配pattern。比如hello(?=world)匹配helloworld能够成功,匹配hellojava则失败。
- (?!pattern) :要求当前位置开始向后的字符串不能匹配pattern。比如hello(?!world)匹配helloworld则失败,匹配hellojava则成功。
- (?<=pattern) :要求当前位置开始向前的字符串能匹配pattern。比如(?<=hello)world匹配helloworld能够成功,匹配hiworld则失败。
- (?<!pattern) :要求当前位置开始向前的字符串不能匹配pattern。比如(?<!hello)world匹配helloworld则失败,匹配hiworld则成功。
特殊:以什么开头:^,以什么结尾:$,这样的匹配为/^pattern$/
七、原子组的用法
- 一对小括号包起来的东西被称为原子组,\0表示当前匹配到的内容,\n,n>0表示与第n个原子组相同的内容
- 原子组里面加上?:表示不记录该原子组,但是原子组的功能仍然生效使用
- 使用?<name> 给原子组起别名 使用 $<name> 读取别名
- 使用$n表示第n个原子组匹配到的内容
- $` : 获取当前匹配到的元素左边的元素;$’ : 获取当前匹配到的元素右边的元素;$& : 获取当前匹配到的元素自身