使用 PCRE 提取 "expression syntax"
Extracting "expression syntax" with PCRE
我们正在开发一个支持从字符串中推断表达式的项目。在幕后,我们使用 Symfony 的表达式语言来提供上下文解析,但我们是从字符串中提取表达式的人。
首先我想说,我不是正则表达式方面的专家。我的工作知识有限,所以下面的正则表达式会显得笨拙和不优雅:
/${(.*?)}(?=[\s\w\-_\/\:;,.?!()|"\]&]|$)/
理论是这样的:
- 表达式以
${
开头。这是起始锚。
- 匹配其中的任何内容。
- 表达式以结束符
}
结尾,后跟行尾 $
或字符列表中的一项。
考虑如下所示的表达式:
他叫“${name}
”,他是“${thing}
”。
正则表达式将成功匹配表达式 name
和 thing
,并将用值对象中的值替换它们。
但是,如果我们考虑到用户也可以解析实际的表达式和值,那么:
${{"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
我们正在开发一个支持从字符串中推断表达式的项目。在幕后,我们使用 Symfony 的表达式语言来提供上下文解析,但我们是从字符串中提取表达式的人。
首先我想说,我不是正则表达式方面的专家。我的工作知识有限,所以下面的正则表达式会显得笨拙和不优雅:
/${(.*?)}(?=[\s\w\-_\/\:;,.?!()|"\]&]|$)/
理论是这样的:
- 表达式以
${
开头。这是起始锚。 - 匹配其中的任何内容。
- 表达式以结束符
}
结尾,后跟行尾$
或字符列表中的一项。
考虑如下所示的表达式:
他叫“${name}
”,他是“${thing}
”。
正则表达式将成功匹配表达式 name
和 thing
,并将用值对象中的值替换它们。
但是,如果我们考虑到用户也可以解析实际的表达式和值,那么:
${{"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