php - 用 PCRE 提取“表达式语法”
问题描述
我们正在开发一个支持字符串外插表达式的项目。在后台,我们使用 Symfony 的表达式语言来提供上下文解析,但我们是从字符串中提取表达式的人。
我想先说一下,我不是正则表达式的专家。我的工作知识有限,因此以下正则表达式会显得笨拙和不雅:
/\${(.*?)}(?=[\s\w\-_\/\\:;,.?!()|"\]&]|$)/
理论是这样的:
- 表达式以 开头
${
。这是起始锚。 - 匹配那里的任何东西。
- 表达式以结束符结尾,
}
后跟行 end$
或字符列表中的一项。
考虑一个看起来像这样的表达式:
他的名字是“ ${name}
”,他是一个“ ${thing}
”。
正则表达式将成功匹配表达式name
and thing
,并将替换为来自值对象的值。
但是,如果我们考虑到用户也可以解析实际的表达式和值,那么:
${{"name": "Pack Rat", "mana_cost": "{1}{B}", "cmc": 2}}
意思是,将该表达式评估为 JSON 对象,正则表达式失败,因为它在}"
part 中的序列处停止{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
推荐阅读
- assembly - 为什么我不能执行二进制文件?
- mirth - 使用 nhapi 添加非标准段
- haskell - 如何为包含函数的新类型构建 fmap
- graphql - 禁用游乐场时,阿波罗服务器返回 GET 查询丢失
- c# - Razor 页面 - 具有多个处理程序/服务器端验证的表单在提交时未填充 asp-validation-for 标记
- curl - 基准测试 curl vs wget vs python-request 库
- javascript - 未在 Testcafe 中运行的测试出现错误“TypeError: Cannot read property 'split' of undefined”
- matlab - Minimize function that takes n vectors as input
- firebase - Firebase Cloud Firestore 中的嵌套文档引用
- visual-studio - 无法为新项目选择 .Net Core 版本