【问题标题】:Extracting "expression syntax" with PCRE用 PCRE 提取“表达式语法”
【发布时间】:2021-08-13 17:16:18
【问题描述】:

我们正在开发一个支持字符串外推表达式的项目。在后台,我们使用 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,但它无法从正则句子中提取两个表达式。

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

【问题讨论】:

    标签: php regex pcre


    【解决方案1】:

    你可以使用

    \$(\{(?:[^{}]+|(?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
    

    【讨论】:

    • 优秀。感谢您的帮助,此解决方案也适用于我们的整个测试套件。人们总是很擅长正则表达式,这总是让我感到惊讶。我需要研究递归和反转我的规则。如果不是太麻烦,我可以请您快速详细说明您的解决方案吗?我了解它的表面水平,但任何细节都将不胜感激。
    • @MorinoAndo:不客气。当然,正则表达式本身就是一种(强大的)语言。一个很好的开始是Mastering Regular Expressions 或网站RexEgg
    • @MorinoAndo:添加了一些解释。
    • 非常感谢!我的老板也是。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 2011-06-11
    • 2017-12-09
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多