PCRE模式用于检测嵌套匹配

3

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

##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##

这里是关于正则表达式的演示

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

如果可能的话,我想避免为此改进编写语言解析器。

非常感谢任何建议!


你到底要用这些匹配做什么?请使用 preg_replace_callback 方法分享一下。 - Wiktor Stribiżew
@Wiktor:这些块是更大文本的一部分,允许系统用户基于这些条件创建动态文本模块。整个条件将被替换为##IF##或##ELSE##部分。函数x()、y()或g()只是用户定义函数集合的示例。 - Andre
1个回答

2

试试这个:

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

它将查找外部if块组。

删除了我的上一条评论,因为它是错误的。这个正则表达式似乎工作得很好。我在循环内使用它,直到没有更多的##IF##语句被找到。您能解释一下为什么第一个原子组 (?>(.*?)##) 是必要的吗? - Andre
它有效地减少了在无匹配情况下的回溯(例如,没有“##ENDIF##”的“##IF”)。如果不可能出现无匹配,则可以省略原子组。 - Michail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接