如何改写匹配双大括号变量的正则以适配XML文档存储?
解决XML中存储含负向预查正则的问题
问题背景
需要判断字符串是否包含{{变量}}格式的内容,原正则(?<!\{)\{\{(?:([^{}]+))}}(?!})可满足测试用例需求,但将JS函数存入XML时,<需转义为<,导致转义后的正则失效。测试用例如下:
| 字符串/变量 | 预期结果 |
|---|---|
文本 {{date}} 文本 | true |
文本 {date}} 文本 | false |
文本 {{date} 文本 | false |
文本 {date{date}} 文本 | false |
文本 {{date}date} 文本 | false |
文本 {{{date}}} 文本 | true |
文本 {date{{date}}date} 文本 | true |
文本 {{date}} 一些文本 {date}} 文本 | true |
原XML存储的JS函数示例:
<script_node> function foo(TextWithEmbeddedVars){ var check = /(?<!\{)\{\{(?:([^{}]+))}}(?!})/.test(TextWithEmbeddedVars); return check; } </script_node>
解决方案
方案一:改写正则,移除负向预查
将原正则中的负向预查(?<!\{)替换为正向匹配(^|[^{]),表示{{要么在字符串开头,要么前面的字符不是{,这样可以完全避免使用<符号,无需转义即可在XML中正常使用。
改写后的正则:
/(^|[^{]){{([^{}]+)}}(?!})/
对应的XML代码:
<script_node> function foo(TextWithEmbeddedVars){ var check = /(^|[^{]){{([^{}]+)}}(?!})/.test(TextWithEmbeddedVars); return check; } </script_node>
该正则可完全覆盖所有测试用例的预期结果。
方案二:使用RegExp构造函数兼容XML转义
若需保留原正则的负向预查逻辑,可通过RegExp构造函数实现。在XML中将<转义为<,同时对正则中的特殊字符({、})进行双重转义(XML中写\\\\{,最终JS解析为\{)。
XML中的代码写法:
<script_node> function foo(TextWithEmbeddedVars){ var regexPattern = "(?<!\\\\{)\\\\{\\\\{([^\\\\{\\\\}]+)\\\\}\\\\}(?!\\\\})"; var check = new RegExp(regexPattern).test(TextWithEmbeddedVars); return check; } </script_node>
这种写法既符合XML的语法规则,又能让JS正确解析出原正则表达式。
内容的提问来源于stack exchange,提问作者Jeff Martinez
相关产品推荐
相关产品推荐

