如何编写匹配嵌套${}$自定义标签的正则表达式?
搞定嵌套${...}$标签的正则匹配问题
原正则/${[\W\w]+?}$/g用了非贪婪匹配,碰到内层标签的}$就直接终止匹配,导致外层的${fields$:...}只能截取到一半。要解决嵌套结构的匹配问题,得用支持平衡匹配的递归正则。
可用的正则表达式(支持ES2018+的JavaScript环境)
/\${(?:(?!\${|}\$)[\s\S]|(?R))*?}\$/g
正则逻辑拆解
\${:精准匹配标签起始符${(?:(?!\${|}\$)[\s\S]|(?R))*?:核心的平衡匹配逻辑,非贪婪重复执行两种情况:(?!\${|}\$)[\s\S]:匹配任意字符(包括换行),只要当前位置不是新标签的开头${或标签结尾}$(?R):递归调用整个正则表达式,专门处理嵌套的${...}$结构
}\$:匹配标签结束符}$/g:全局匹配所有符合规则的标签
测试验证
将该正则应用到你的待匹配文本中:
const input = `constructor(public props: ${ClassName}$Model) { super() ${fields$: this._#{key}# = this.initProp(this, new #{value:1}#(props?.#{key}#, '#{key}# da ${ClassName}$')) }$ }`; const regex = /\${(?:(?!\${|}\$)[\s\S]|(?R))*?}\$/g; const results = input.match(regex); console.log(results);
输出结果完全符合你的期望:
[ "${ClassName}$", "${fields$:\n this._#{key}# = this.initProp(this, new #{value:1}#(props?.#{key}#, '#{key}# da ${ClassName}$'))\n}$" ]
额外说明
- 如果运行环境不支持递归正则(比如旧版本JavaScript),可以改用平衡组语法(如.NET环境的
(?<open>\${)和(?<close-open>}\$)),或者通过代码计数嵌套层级的方式辅助匹配。 - 若标签中存在转义的
\${(需要匹配字面量而非标签),则需要给正则添加转义处理规则。
内容的提问来源于stack exchange,提问作者Ricardo Tadeu Sinhei Arakaki
相关产品推荐
相关产品推荐

