【问题标题】:PCRE pattern to detect nested matches检测嵌套匹配的 PCRE 模式
【发布时间】:2019-01-03 11:39:48
【问题描述】:

我使用以下模式来匹配和替换使用preg_replace_callback 的简单IF-ELSE-ENDIF 块:

##IF (.*?)##(.*?)(?:##ELSE##(.*?))?##ENDIF##

以下两个例子匹配替换正确

1. ##IF x()## foo ##ENDIF##

Result:

Group 1: `x()`
Group 2: ` foo `

2. ##IF y()## foo ##ELSE## bar ##ENDIF##

Result:

Group 1: `y()`
Group 2: ` foo `
Group 3: ` bar `

现在我想增强此功能以允许嵌套 IF-ELSE 块,例如

##IF g()## pre-outer-if ##IF h()## inner-if ##ENDIF## post-outer-if ##ELSE## outer-else ##ENDIF##

这里是 regex101.com 上的a demo

我尝试使用递归运算符和正向前瞻来增强模式,但没有成功。目标是匹配和替换相关的 IF-ELSE-ENDIF 块,以允许用户定义条件文本块。

如果可能,我想避免为此增强编写语言解析器。

非常感谢您的任何建议!

【问题讨论】:

  • 你到底在用火柴做什么?方法请分享给preg_replace_callback
  • @Wiktor:这些块是更大文本的一部分,允许系统用户根据这些条件创建动态文本模块。整个条件由##IF## 或##ELSE## 部分替换。函数 x()、y() 或 g() 只是一组用户定义函数的示例。

标签: php regex recursion pcre


【解决方案1】:

试试这个:

##IF (?>(.*?)##)((?>(?0)|.)*?)(?:##ELSE##((?>(?0)|.)*?))?##ENDIF##

它会找到一个外部的 if-block 组。

【讨论】:

  • 删除了我的最后一条评论,因为它是错误的。这个正则表达式似乎工作正常。我在循环中使用它,直到找不到更多 ##IF## 语句。你能解释一下为什么第一个原子组(?>(.*?)##) 是必要的吗?
  • 它有效地减少了不匹配情况下的回溯(例如,##IF witout ##ENDIF##)。如果不能出现不匹配,则可以省略原子组。
猜你喜欢
  • 1970-01-01
  • 2022-01-11
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多