使用 PCRE 提取 "expression syntax"

Extracting "expression syntax" with PCRE

我们正在开发一个支持从字符串中推断表达式的项目。在幕后,我们使用 Symfony 的表达式语言来提供上下文解析,但我们是从字符串中提取表达式的人。

首先我想说,我不是正则表达式方面的专家。我的工作知识有限,所以下面的正则表达式会显得笨拙和不优雅:

/${(.*?)}(?=[\s\w\-_\/\:;,.?!()|"\]&]|$)/

理论是这样的:

  1. 表达式以 ${ 开头。这是起始锚。
  2. 匹配其中的任何内容。
  3. 表达式以结束符 } 结尾,后跟行尾 $ 或字符列表中的一项。

考虑如下所示的表达式:

他叫“${name}”,他是“${thing}”。

正则表达式将成功匹配表达式 namething,并将用值对象中的值替换它们。

但是,如果我们考虑到用户也可以解析实际的表达式和值,那么:

${{"name": "Pack Rat", "mana_cost": "{1}{B}", "cmc": 2}}

意思是,将该表达式计算为 JSON 对象,正则表达式失败,因为它在 {1}{B} 部分的 }" 序列处停止,并且仅匹配 {"name": "Pack Rat", "mana_cost": "{1}{B .删除 " 作为前瞻字符列表中可能的停止点可修复 JSON,但随后无法从正则句中提取这两个表达式。

是否可以避免此表达式解析器过早停止?或者这是否超出了单个正则表达式的范围?

你可以使用

$(\{(?:[^{}]+|(?1))+\})

并以此进一步分析。参见 a demo on regex101.com


详细内容如下:

$                       # "$" literally
(                        # opening bracket -> capture group 1
    \{                   # "{" literally
        (?:[^{}]+|(?1))+ # not { nor } or repeat the first group -> recursion
    \}                   # "}" 
)                        # end of group 1