跳至主要內容

11.正则表达式

pinia原创大约 7 分钟正则

一、介绍

  • 正则表达式(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: 匹配xy字符
  • [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 
/正则表达式主体/修饰符(可选)
  • 修饰符
    1. g: 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
    2. i: 执行对大小写不敏感的匹配。
    3. m: 执行多行匹配。
    4. s: 执行特殊字符圆点.中包含换行符的匹配。
    5. u: 使用unicode码的模式进行匹配
    6. y: 执行高效匹配,只要下一个字符不满足匹配条件,就会停止匹配。
上次编辑于:
贡献者: 林深不见鹿