JS之正则表达式

190 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

正则表达式 RegExp

有三种表达方式:

  1. 字面量 /ab/i
  2. RegExp(字符串,修饰符) RegExp('ab','i')
  3. RegExp(正则表达式,修饰符) RegExp(/ab/,'i')
    const reg1 = /pig/i
    const reg2 = RegExp('pig','i')
    const reg3 = RegExp(/pig/,'i')
    

lastIndex

RegExp.lastIndex 是正则表达式的一个可读可写的整型属性,用来指定下一次匹配的起始索引

  • 如果lastIndex大于字符串长度,则test()exec()失败,lastIndex被设置为0。

  • 如果 lastIndex 等于或小于字符串的长度,则该正则表达式匹配从 lastIndex 位置开始的字符串。

  • 如果 test() 和 exec() 匹配成功,lastIndex 会被设置为紧随最近一次成功匹配的下一个位置。如果test()exec()匹配失败,lastIndex 会被设置为 0

test()和exec()都是RegExp的实例方法,这里将介绍几个常用的实例方法

常用实例方法

test()

用来查看正则表达式与指定的字符串是否匹配。返回 true 或 false

const str = 'I love cute pig and piggy'
const regex = new RegExp('pig*'); // 匹配出现零次或多次的pig
const globalRegex = new RegExp('pig*', 'g'); // g表示全局匹配,查找所有匹配的pig

console.log(regex.test(str)); // true

console.log(globalRegex.lastIndex); // 0:还没开始匹配的时候,默认开始位置是0

console.log(globalRegex.test(str)); // true:判断是否存在指定字符'pig'

console.log(globalRegex.lastIndex); // 15:第一次匹配完的位置,也是下一次开始匹配的位置

console.log(globalRegex.test(str)); // true:15位置后是否存在指定字符'pig'

console.log(globalRegex.lastIndex); // 24:第一次匹配完的位置,也是下一次开始匹配的位置

console.log(globalRegex.test(str)); // false:24位置后是否存在指定字符'pig'

console.log(globalRegex.lastIndex); // 0:根据匹配规则,失败lastIndex变为0

exec()

用来在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null,相当于字符串 str.match(regexp) 方法。

// reg.exec()
const reg = /pig/
const str = 'I love cute pig and piggy'
const result = reg.exec(str)
console.log(result)
// 输出如下:
0: "pig"
groups: undefined // 捕获组
index: 12 // 匹配项的开始位置
input: "I love cute pig and piggy" // 输入字符串,等于 str
length: 1

// str.match(regexp) 注意regexp不能带修饰符g
const str = 'I love cute pig and piggy'
const result = str.match(/pig/)
console.log(result)  
// 输出如下:
0: "piggy" //完整匹配
groups: undefined
index: 20
input: "I love cute pig and piggy"
length: 1

match()

字符串执行匹配并返回匹配结果,匹配成功返回数组,匹配不成功返回null。写法:reg[Symbol.match](str),相较于String.match(reg),正则的match写法我个人觉得不是很好记。

仔细观察会发现match()和exec()返回的结果一样。

const reg = /pig/
const str = 'I love cute pig and piggy'
const result = reg[Symbol.match](str)
console.log(result)
1.  0: "pig"
1.  groups: undefined
1.  index: 12
1.  input: "I love cute pig and piggy"
1.  length: 1

matchAll

返回对字符串使用正则表达式的所有匹配项,返回值是迭代器。与String.matchAll(reg)方法一样。可以使用for...of循环取出

const reg = /pig/
const str = 'I love cute pig and piggy'
const result = reg[Symbol.matchAll](str)
console.log(result) // RegExpStringIterator {}
console.log(Array.from(result, x => x[0])); // ['pig']
// for...of
for(const match of str.matchAll(/pig/g)) {  // 需要注意 matchAll需要修饰符g,不然会报错
    console.log(match)
}

replace()

替换所有符合正则模式的匹配项,并返回替换后的新字符串结果,不改变原字符串。与String.replace(reg)方法一样。

const reg = /pig/
const str = 'I love cute pig and piggy'
const result = reg[Symbol.replace](str,'cat')
console.log(result) // I love cute cat and piggy

// 全局替换
const reg = /pig/g
const str = 'I love cute pig and piggy'
const result = reg[Symbol.replace](str,'cat')
console.log(result) // I love cute cat and catgy

search()

在给定字符串中的一个搜索目标字符串,返回值是整数(成功则返回该正则模式的第一个匹配项的在字符串中的位置索引。失败则返回-1)。与String.search(reg)方法一样。

// 找到
const reg = /pig/
const str = 'I love cute pig and piggy'
const result = reg[Symbol.search](str)
console.log(result) // 12

// 找不到
const reg = /cat/
const str = 'I love cute pig and piggy'
const result = reg[Symbol.search](str)
console.log(result) // -1

split()

切割字符串,返回值数组。与String.split()方法一样。

const reg = /\s/
const str = 'I love cute pig and piggy'
const result = reg[Symbol.split](str)
console.log(result) // (6) ['I', 'love', 'cute', 'pig', 'and', 'piggy']

参考

MDN中关于match的介绍

总结

正则表达式和字符串在匹配上有很多相似的地方或方法名,在使用时正则的常用test和exec、其余时候还是用String的匹配比较多,但如果需要对匹配进行处理,可以使用正则的匹配。 写法参考如下:

// 写法
class RegExp1 extends RegExp {
  [Symbol.实例方法名](str) {
    const result = RegExp.prototype[Symbol.实例方法名].call(this, str);
    if (result) {
      return 'VALID';
    }
    return 'INVALID';
  }
}
// 以replace为例
class RegExp1 extends RegExp {
  [Symbol.replace](str) {
    return RegExp.prototype[Symbol.replace].call(this, str, '#!@?');
  }
}

console.log('football'.replace(new RegExp1('foo')));

寒冬时期,互帮互助,祝我们顺利上岸!