Php 用于处理由{和}包围的嵌套字符串的递归正则表达式

Php 用于处理由{和}包围的嵌套字符串的递归正则表达式,php,regex,recursion,Php,Regex,Recursion,在一个项目中,我有这样一个模式的文本: {|文本{|文本}文本} 更多文本 我想把第一部分用括号括起来。为此,我递归地使用preg_匹配。以下代码已经可以正常工作了: preg_match('/\{((?>[^\{\}]+)|(?R))*\}/x',$text,$matches); 但是如果我添加符号“|”,我得到的结果是空的,我不知道为什么: preg_match('/\{\|((?>[^\{\}]+)|(?R))*\|\}/x',$text,$matches); 我不能使用第

在一个项目中,我有这样一个模式的文本:

{|文本{|文本}文本}
更多文本

我想把第一部分用括号括起来。为此,我递归地使用preg_匹配。以下代码已经可以正常工作了:

preg_match('/\{((?>[^\{\}]+)|(?R))*\}/x',$text,$matches);
但是如果我添加符号“|”,我得到的结果是空的,我不知道为什么:

preg_match('/\{\|((?>[^\{\}]+)|(?R))*\|\}/x',$text,$matches);
我不能使用第一个解决方案,因为在文本中也可以存在类似{text}的内容。有人能告诉我我做错了什么吗?Thx参见

使其适应您的使用

preg_match_all('/\{\|(?:^(\{\||\|\})|(?R))*\|\}/', $text, $matches);

使其适应您的使用

preg_match_all('/\{\|(?:^(\{\||\|\})|(?R))*\|\}/', $text, $matches);
试试这个:

'/(?s)\{\|(?:(?:(?!\{\||\|\}).)++|(?R))*\|\}/'
在原始正则表达式中,使用字符类
[^{}]
匹配除分隔符以外的任何内容。如果分隔符仅为一个字符,但您的分隔符为两个字符,则这很好。要与多字符序列不匹配,您需要以下内容:

(?:(?!\{\||\|\}).)++
点匹配任何字符(包括换行符,这要感谢
(?s)
),但只有在先行检查确定它不是
{
}
序列的一部分之后。我还删除了您的原子组(
(?>…)
),并将其替换为所有格量词(
++
),以减少混乱。但您必须在正则表达式的该部分中使用一个或另一个来防止。

尝试以下方法:

'/(?s)\{\|(?:(?:(?!\{\||\|\}).)++|(?R))*\|\}/'
在原始正则表达式中,使用字符类
[^{}]
匹配除分隔符以外的任何内容。如果分隔符仅为一个字符,但您的分隔符为两个字符,则这很好。要与多字符序列不匹配,您需要以下内容:

(?:(?!\{\||\|\}).)++

点匹配任何字符(包括换行符,这要感谢
(?s)
),但只有在先行检查确定它不是
{
}
序列的一部分之后。我还删除了您的原子组(
(?>…)
),并将其替换为所有格量词(
++
),以减少混乱。但是您肯定应该在正则表达式的这一部分中使用其中一个,以防止出现这种情况。

您对使用正则表达式有一些建议,但是如果您想知道原始正则表达式失败的原因,请继续阅读。问题在于何时匹配结束“|}”标记。
(?>[^{}]+)
(或
[^{}]+
)子表达式将与“|”匹配,导致
}
子表达式失败。如果子表达式中没有回溯,则无法从失败的匹配中恢复。

您对使用正则表达式有一些建议,但如果您想知道原始regexp失败的原因,请继续阅读。问题在于何时匹配结束“|}”标记。
(?>[^{}]+)
(或
[^{}]+
)子表达式将与“|”匹配,导致
}
子表达式失败。由于子表达式中没有回溯,因此无法从失败的匹配中恢复。

我刚刚尝试了您的解决方案,效果很好。非常感谢你!也谢谢你的解释,因为这不容易理解。我刚刚尝试了你的解决方案,效果很好。非常感谢你!同时也感谢您的解释,因为这不容易理解。您可以在.NET中使用平衡组,如下所述:您可以在.NET中使用平衡组,如下所述: