11.正则表达式
一、介绍
- 正则表达式(Regular Expression),又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合, 组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
二、正则表达式创建
// 方法一, 通过`/``/`之间写入表达式
var re = /ab+c/
// 方法二,通过对象 RegExp创建, 第一个参数是字符串表达式,后一个参数是标志,参考后文
var re = new RegExp("ab+c", "flags")
// 如果正则表达式不变,一般用第一种,如果正则表达式会根据程序运行动态改变,就要用第二种。
// 通过字符串表达式创建的正则,需要转义的字符有以下几个
// [ ] \ ^ $ . | ? * + ( )
三、表达式的方法
3.1RegExp对象
3.1.1.exec()
- exec()方法检索字符串中的指定值。返回值是被找到的值。如果没有发现匹配,则返回 null。
- 使用exec方法时RegExp 对象的lastIndex属性会保留上次检索到的位置,下次使用exec()方法检索时从该位置开始,若没有检索到则为空。
- 语法:
reg.exec(str)
/lu/g.exec('gaolululove')
输出:['lu', index: 3, input: 'gaolululove', groups: undefined]
3.1.2.test()
搜索字符串指定的值,根据结果并返回真或假。
语法:
reg.test(str)
/^lu/g.test('gaolululove')
输出:true
3.2字符串方法
3.2.1match()
检索与正则表达式相匹配的子字符串,它是一次匹配,只要找到了一个匹配的结果就会返回, 而不是查找所有匹配的结果。
该方法也可使用字符串作为参数,字符串参数会转换为正则表达式。
语法:
str.match(regexp)
'gaolululove'.match(/ulo/)
输出:['ulo', index: 6, input: 'gaolululove', groups: undefined]
3.2.2matchAll()
ES11的新特性,matchAll() 方法返回一个包含所有匹配正则表达式的结果的迭代器。可以使用 for…of 遍历,或者使用 展开运算符(…) 或者 Array.from 转换为数组。
如果所传参数不是一个正则表达式对象,则会隐式地使用
new RegExp(obj)将其转换为一个 RegExp。如果RegExp对象没有==/g==标志,则将引发TypeError 。语法:
str.matchAll(regexp)语法:
regexp[Symbol.matchAll](str)
var res = '2016-01-02'.matchAll(/[0-9]+/g);
console.log(Array.from(res, item => item[0]));
输出:["2016", "01", "02"]
3.2.3search()
匹配到返回索引,未匹配到返回-1。
用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置。
search方法可使用字符串作为参数,字符串参数会转换为正则表达式。
语法:
str.search(reg)
'gaolululove'.search(/ulo/)
输出:6
3.2.4replace()
替换匹配数据
用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串,并返回替换后的新字符串。
replace方法可使用字符串作为参数,字符串参数会转换为正则表达式。
语法:
str.replace(regexp,“text”)
'gaolululove'.replace(/love/,'')
输出:'gaolulu'
3.2.5split
把字符串分割为字符串数组,返回值为分割后数组。
语法:
str.split(reg)
'gaolululove'.split('l')
输出: ['gao', 'u', 'u', 'ove']
3.3exec()全局匹配与实现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);
}
四、特殊字符表
4.1断言类
^: 匹配输入字符串的开始位置$: 匹配输入字符串的结尾位置\b: 匹配「单词」和「非单词」边界\B: 匹配同类的边界,即「单词」与「单词」之间,「非单词」与「非单词」之间的边界x(?=pattern): 向前断言,要求当前位置开始向后的字符串能匹配pattern。比如hello(?=world)匹配helloworld能够成功,匹配hellojava则失败。x(?!pattern): 向前否定断言,要求当前位置开始向后的字符串不能匹配pattern。比如hello(?!world)匹配helloworld则失败,匹配hellojava则成功。(?<=pattern)x: 向后断言,要求当前位置开始向前的字符串能匹配pattern。比如(?<=hello)world匹配helloworld能够成功,匹配hiworld则失败。(?<!pattern)x: 要求当前位置开始向前的字符串不能匹配pattern。比如(?<!hello)world匹配helloworld则失败,匹配hiworld则成功。
::: 注意
- 「单词」边界中的「单词」在js中指的是
\w,即[a-zA-Z0-9_],除此之外称为「非单词」
:::
4.2字符类
.: 表示匹配除换行符 \n 之外的任何单字符[.\n]:表示匹配任意字符\d: 表示匹配数字。相当于[0-9]\D: 表示匹配除了数字以外任意字符。相当于[^0-9][\d\D]:表示匹配任意字符\w: 表示匹配数字、字母、下划线\W: 表示匹配非数字、字母、下划线的任何字符[\w\W]:表示匹配任意字符\s: 表示匹配任何空白字符,包含以下几个,相当于==[\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]==- 空格符 (space character)
- 制表符 (tab character)
- 回车符 (carriage return character)
- 换行符 (new line character)
- 垂直换行符 (vertical tab character)
- 换页符 (form feed character)
\S: 表示匹配任何非空白字符,相当于[^\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff][\s\S]:表示匹配任意字符\t: 匹配制表符 (tab character)\r: 匹配回车符 (carriage return character)\n: 匹配换行符 (new line character)\v: 匹配垂直换行符 (vertical tab character)\f: 匹配换页符 (form feed character)[\b]: 匹配退格符(backspace)\0: 匹配 null字符\xhh: 匹配两位十六进制数\uhhhh: 匹配四位十六进制,Unicode字符
4.3组和范围
x|y: 匹配x或y字符[A-Z]: 匹配 A到Z的字符集合,其中-为连字符,如果放在开头或结尾将作为普通字符匹配[^A-Z]: 匹配除[A-Z]以外的字符(x): 捕获组,匹配x并记住x\n:n是正整数,引用之前的捕获,例如:/abc(d)ef\1/匹配abcdefg,得到abcdefd
4.4量词
x*: 将x匹配0次以上x+: 将x匹配1次以上x?: 将x匹配0次或1次x{n}: 将x匹配n次,n 是一个非负整数。x{n,}: 将x匹配n次以上,n 是一个非负整数。x{n,m}: 将x匹配n次以上,m次以下,m 和 n 均为非负整数。x*?, x+?, x??, x{n}?, x{n,}?, x{n,m}?: 原本x*, x+, x?, x{n}, x{n,}, x{n,m}匹配的是贪婪匹配的,后面加上?之后,匹配将变成惰性匹配
贪婪匹配与惰性匹配
- 贪婪匹配——在匹配成功的前提下,尽可能多的去匹配
- 惰性匹配——在匹配成功的前提下,尽可能少的去匹配
注意:默认的贪婪匹配是从后往前最大长度的匹配,惰性匹配就是在贪婪量词后面加个==?==从字符串的前面开始匹配,最小长度的匹配
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"]
五、正则表达式标志
- 正则表达式有六个可选参数 (flags) 允许全局和不分大小写搜索等。这些参数既可以单独使用也能以任意顺序一起使用, 并且被包含在正则表达式实例中
- 语法
/pattern/flags
/正则表达式主体/修饰符(可选)
- 修饰符
g: 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。i: 执行对大小写不敏感的匹配。m: 执行多行匹配。s: 执行特殊字符圆点.中包含换行符的匹配。u: 使用unicode码的模式进行匹配y: 执行高效匹配,只要下一个字符不满足匹配条件,就会停止匹配。