我们正在进行一个项目,支持从字符串中推断表达式。在后台,我们使用Symfony的表达式语言来提供上下文解析,但我们是从字符串中提取表达式的人。
在这之前,我想说,我不是正则表达式方面的专家。我的工作知识有限,因此以下正则表达式将显得笨拙和不雅:
/${(.*?)}(?=[sw-_/\:;,.?!()|"]&]|$)/
因此,理论是:
- 表达式以
${
开头。这是起锚 - 匹配里面的任何东西
- 表达式以结束
}
结尾,后面跟着行结束$
或字符列表中的一个项
考虑一个看起来像这样的表达式:
他的名字是";CCD_ 5";,他是一个";${thing}
";。
正则表达式将成功匹配表达式name
和thing
,并将它们替换为值对象中的值。
然而,如果我们考虑到用户也可以解析实际的表达式和值,则如下所示:
${{"name": "Pack Rat", "mana_cost": "{1}{B}", "cmc": 2}}
也就是说,将该表达式求值为JSON对象,正则表达式失败,因为它在部分{1}{B}
中的}"
序列处停止,并且只匹配{"name": "Pack Rat", "mana_cost": "{1}{B
。删除"
作为先行字符列表中可能的停止点可以修复JSON,但随后无法从正则语句中提取这两个表达式。
有可能避免这个表达式解析器过早停止吗?还是这超出了单个正则表达式的范围?
您可以使用
$({(?:[^{}]+|(?1))+})
并以此进行进一步分析。请参阅regex101.com上的演示。
详细信息如下:
$ # "$" literally
( # opening bracket -> capture group 1
{ # "{" literally
(?:[^{}]+|(?1))+ # not { nor } or repeat the first group -> recursion
} # "}"
) # end of group 1