正则表达式

2024/09/06

基础知识

基础字符匹配

元字符含义

字符集和预定义字符

分组和捕获

零宽断言

其他

应用示例

JS RegExp 相关 API

RegExp.prototype.exec()

exec(str): 如果匹配成功,返回一个数组,数组的第一个元素是匹配的完整字符串,后续元素是捕获组的内容;如果没有匹配到,返回 null

/(\d+)-(\d+)/.exec('The date is 2023-10-15') // ['2023-10', '2023', '10', index: 12, input: 'The date is 2023-10-15', groups: undefined]

RegExp.prototype.test()

test(str): 如果正则表达式和字符串之间匹配 str 的否则为 false

/abc/i.test('ABC is here') // true

RegExp.prototype.toString()

RegExp.prototype[Symbol.match]()

"Hello, hello!".match(/hello/i) //  ['Hello', index: 0, input: 'Hello, hello!', groups: undefined ]
"Hello, hello!".match(/hello/gi) //  [ 'Hello', 'hello' ]

RegExp.prototype[Symbol.matchAll]()

matchAll() 方法返回一个迭代器对象,该迭代器中的每个元素都是一个数组,数组的格式与 match() 方法在不使用全局标志 g 时返回的数组格式相同,包含匹配到的完整字符串、捕获组信息以及 index 和 input 属性。如果没有匹配到任何结果,迭代器为空。

"Hello, hello!".matchAll(/hello/gi)]
// [ 'Hello', index: 0, input: 'Hello, hello!', groups: undefined ]
// [ 'hello', index: 7, input: 'Hello, hello!', groups: undefined ]

RegExp.prototype[Symbol.replace](pattern, replacement)

pattern: 可以是一个字符串或者一个正则表达式。如果是字符串,它只会替换匹配到的第一个子字符串;如果是正则表达式,它会根据正则表达式的规则进行匹配替换,并且如果正则表达式带有 g 全局标志,则会替换所有匹配的子字符串 replacement: 可以是一个字符串或者一个函数。如果是字符串,它会替换掉匹配到的内容;如果是函数,该函数会在每次匹配时被调用,函数的返回值将作为替换的内容

"Hello, hello!".replace(/hello/i, '你好') // '你好, hello!'
"Hello, hello!".replace(/hello/gi, (v) => `${v}`.toUpperCase()) // 'HELLO, HELLO!'

RegExp.prototype[Symbol.replaceAll](pattern, replacement)

pattern: 可以是一个字符串或者一个正则表达式。如果是正则表达式,必须带有 g 全局标志,否则会抛出错误 replacement: 可以是一个字符串或者一个函数,作用和 replace() 方法的第二个参数相同

"Hello, hello!".replaceAll(/hello/gi, '你好') // '你好, 你好!'

RegExp.prototype[Symbol.search](regexp)

regexp: 正则表达式对象或具有 Symbol.search 方法的任何对象, 如果 regexp 不是 RegExp 对象并且没有 Symbol.search 方法,则使用 new RegExp(regexp) 将其隐式转换为 RegExp 返回值: 执行正则表达式和此字符串之间的匹配项的搜索,返回字符串中第一个匹配项的索引

'2020-01-02'.search(/-/g) // 4

RegExp.prototype[Symbol.split]()

性能问题

当正则表达式包含大量的可选分支、嵌套的分组、重复字符(如 *、+、? 等)以及复杂的字符类时,其匹配过程会变得非常复杂,从而导致性能下降。回溯是正则表达式匹配过程中的一种机制,当匹配失败时,正则引擎会回溯到之前的状态,尝试其他可能的匹配路径。

例如过多的回溯会导致性能急剧下降。例如,正则表达式 /.+(\d+)+/ 匹配字符串 abc123def456 时,(.+) 会尽可能多地匹配字符,然后 (\d+)+ 尝试匹配数字。如果匹配失败,正则引擎会回溯 (.+) 匹配的字符,重新尝试 (\d+)+ 的匹配,这个过程可能会重复多次,消耗大量时间。这种情况下,可以考虑使用其他更高效的数据处理方法,如基于字符串分割。

/\s*,\s*/.test('\t'.repeat(N) + '\x00,') 执行时间变化图

你可以在https://devina.io/redos-checker 检查正则表达式是否存在潜在的拒绝服务漏洞

参考文档

Edit this page on GitHub