JavaScript替换文本时如何跳过已被A()包裹的内容
实现方案
核心思路是通过带全局标识的正则匹配实现多匹配项替换,同时通过正则的零宽断言规则自动跳过已被A(...)包裹的内容,全程不需要使用replaceAll方法,完全避免重复包裹问题。
首先需要先对匹配关键词做正则特殊字符转义,避免关键词包含.、*、?等正则元字符时匹配异常,再构造符合排除规则的正则即可,完整实现如下:
// 转义正则特殊字符,避免匹配异常 function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // 核心替换逻辑 let text = "Hello hi Hello!" let selection = "Hello" const escapedSel = escapeRegExp(selection) // 构造全局匹配正则,自动排除已在A()包裹内的内容 const matchReg = new RegExp(`(?<!A\\()${escapedSel}(?![^)]*\\))`, 'g') const result = text.replace(matchReg, `A(${selection})`) console.log(result) // 输出:A(Hello) hi A(Hello)!
规则验证
针对重复执行替换的场景也完全符合要求:
// 模拟首次替换后新增Hello的场景 let text = "A(Hello) hi Hello" let selection = "Hello" const escapedSel = escapeRegExp(selection) const matchReg = new RegExp(`(?<!A\\()${escapedSel}(?![^)]*\\))`, 'g') const result = text.replace(matchReg, `A(${selection})`) console.log(result) // 输出:A(Hello) hi A(Hello),无重复包裹问题
正则规则说明
(?<!A\():负向后行断言,要求匹配的内容前面不能是A(,跳过A(后面紧跟的目标内容(?![^)]*\)):负向前行断言,要求匹配的内容后面不会直接闭合到外层的),跳过所有已经在A(...)内部的目标内容- 末尾的
g是全局匹配标识,会自动匹配所有符合规则的目标内容,无需调用replaceAll
如果需要支持不区分大小写匹配,把正则第二个参数改为gi即可。
内容的提问来源于stack exchange,提问作者Hejhejhej123
相关产品推荐
相关产品推荐

