正则匹配 match 和 exec
在 JavaScript 中常用正则匹配方法有 match
和 exec
, 这两个方法属于不同的对象方法。
match
是字符串方法,写法为:str.match(regex)
exec
是正则表达式方法,写法为:regex.exec(str)
两者在匹配成功时返回的都是数组,在没有匹配上时返回的都是 null,在一些情况下两者返回的结果相同,故在没有深入了解两者的使用规则前,会误以为两者的使用效果是一样的,容易造成误用。在有全局匹配和分组的情况下,两个有很大差异。
全局匹配
当不使用全局匹配时,两者的匹配效果是一样的,仅返回第一次匹配成功的结果:
const str = 'aaa bbb ccc' const regex = /\b\w+\b/ console.log('match:', str.match(regex)) console.log('exec:', regex.exec(str)) // match: [ 'aaa', index: 0, input: 'aaa bbb ccc', groups: undefined ] // exec: [ 'aaa', index: 0, input: 'aaa bbb ccc', groups: undefined ]
当使用全局匹配时,两者的匹配结果出现区别:
const str = 'aaa bbb ccc' const regex = /\b\w+\b/g console.log('match1:', str.match(regex)) console.log('match2:', str.match(regex)) console.log('match3:', str.match(regex)) console.log('exec1:', regex.exec(str)) console.log('exec2:', regex.exec(str)) console.log('exec3:', regex.exec(str)) // match1: [ 'aaa', 'bbb', 'ccc' ] // match2: [ 'aaa', 'bbb', 'ccc' ] // match3: [ 'aaa', 'bbb', 'ccc' ] // exec1: [ 'aaa', index: 0, input: 'aaa bbb ccc', groups: undefined ] // exec2: [ 'bbb', index: 4, input: 'aaa bbb ccc', groups: undefined ] // exec3: [ 'ccc', index: 8, input: 'aaa bbb ccc', groups: undefined ]
总结:
- 无全局匹配时,match 和 exec 效果一样,仅返回第一次匹配成功的结果;
- 全局匹配时,match 会返回所有匹配上的内容;而 exec 仅匹配单次匹配上的内容,当多次匹配时,exec 会从上次匹配结束的下一位开始匹配,返回本次匹配上的内容,直至无可以匹配的内容,返回 null。
分组
无全局匹配且分组时,match 和 exec 返回结果相同,此时由于表达式采用了括号分组,所以在返回匹配结果的同时,依次返回该结果的所有分组:
const str = 'aaa1 bbb2 ccc3' const regex = /\b(\w+)(\d+)\b/ console.log('match1:', str.match(regex)) console.log('match2:', str.match(regex)) console.log('match3:', str.match(regex)) console.log('exec1:', regex.exec(str)) console.log('exec2:', regex.exec(str)) console.log('exec3:', regex.exec(str)) // match1: ["aaa1", "aaa", "1", index: 0, input: "aaa1 bbb2 ccc3", groups: undefined] // match2: ["aaa1", "aaa", "1", index: 0, input: "aaa1 bbb2 ccc3", groups: undefined] // match3: ["aaa1", "aaa", "1", index: 0, input: "aaa1 bbb2 ccc3", groups: undefined] // exec1: ["aaa1", "aaa", "1", index: 0, input: "aaa1 bbb2 ccc3", groups: undefined] // exec2: ["aaa1", "aaa", "1", index: 0, input: "aaa1 bbb2 ccc3", groups: undefined] // exec3: ["aaa1", "aaa", "1", index: 0, input: "aaa1 bbb2 ccc3", groups: undefined]
全局匹配且分组时,match 和 exec 返回结果不同。match 会返回所有匹配到的结果,而 exec 会返回本次匹配到的结果,若表达式中出现分组,则会依次返回本次匹配的全部分组:
const str = 'aaa1 bbb2 ccc3' const regex = /\b(\w+)(\d+)\b/g console.log('match1:', str.match(regex)) console.log('match2:', str.match(regex)) console.log('match3:', str.match(regex)) console.log('exec1:', regex.exec(str)) console.log('exec2:', regex.exec(str)) console.log('exec3:', regex.exec(str)) // match1: ["aaa1", "bbb2", "ccc3"] // match2: ["aaa1", "bbb2", "ccc3"] // match3: ["aaa1", "bbb2", "ccc3"] // exec1: ["aaa1", "aaa", "1", index: 0, input: "aaa1 bbb2 ccc3", groups: undefined] // exec2: ["bbb2", "bbb", "2", index: 5, input: "aaa1 bbb2 ccc3", groups: undefined] // exec3: ["ccc3", "ccc", "3", index: 10, input: "aaa1 bbb2 ccc3", groups: undefined]
实战
// 匹配十六进制颜色值 const regex = /#([0-9a-zA-Z]{6}|[0-9a-zA-Z]{3})/g const str = `#ffbbad #Fc01DF #FFF #ffE` let m while ((m = regex.exec(str)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === regex.lastIndex) { regex.lastIndex++ } // The result can be accessed through the `m`-variable. m.forEach((match, groupIndex) => { console.log(`Found match, group ${groupIndex}: ${match}`) }) } // Found match, group 0: #ffbbad // Found match, group 1: ffbbad // Found match, group 0: #Fc01DF // Found match, group 1: Fc01DF // Found match, group 0: #FFF // Found match, group 1: FFF // Found match, group 0: #ffE // Found match, group 1: ffE
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 正则匹配汉字
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论