Php 匹配不在花括号内的文本,同时捕获后面的括号
我的情况需要递归,我能够以我需要的方式匹配花括号中的内容,但我无法捕获周围的文本 这就是示例文本: 这是foo{{foo}}和{bar.function({{demo.function({{inner}}==“demo”)}}和{{bar}或“foo”)}更多的文本{{foo 我需要我的结果如下所示:Php 匹配不在花括号内的文本,同时捕获后面的括号,php,regex,Php,Regex,我的情况需要递归,我能够以我需要的方式匹配花括号中的内容,但我无法捕获周围的文本 这就是示例文本: 这是foo{{foo}}和{bar.function({{demo.function({{inner}}==“demo”)}}和{{bar}或“foo”)}更多的文本{{foo 我需要我的结果如下所示: 0 => This is foo 1 => {{foo}} 2 => and 3 =>
0 => This is foo
1 => {{foo}}
2 => and
3 => {{bar.function({{demo.funtion({{inner}} == "demo")}} and {{bar}} or "foo")}}
4 => more_text {{foo
有了这个:({{({{{{}}]{124(?R))*}}
我已经能够很好地匹配{{foo}}
和{bar.function({{demo.function({{internal}}==“demo”)}和{bar}}或“foo”)}
了,但不能匹配周围的文本来达到我需要的结果
我尝试了很多方法,但都没有成功。您可以使用以下基于and
PREG\u SPLIT\u DELIM\u CAPTURE
标志的解决方案:
$re = '/({{(?:[^{}]++|(?R))*}})/';
$str = 'This is foo {{foo}} and {{bar.function({{demo.funtion({{inner}} == "demo")}} and {{bar}} or "foo")}} more_text {{foo';
$res = preg_split($re, $str, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
print_r($res);
// => Array
(
[0] => This is foo
[1] => {{foo}}
[2] => and
[3] => {{bar.function({{demo.funtion({{inner}} == "demo")}} and {{bar}} or "foo")}}
[4] => more_text {{foo
)
看
整个模式由外部捕获组捕获,这就是为什么在添加PREG_SPLIT_DELIM_CAPTURE
时,会将此文本(拆分后)添加到输出数组中
如果存在不需要的空元素,PREG\u SPLIT\u NO\u empty
标志将丢弃它们
更多详细信息:
模式:我从模式中删除了不必要的转义符和符号,因为当上下文足以让rege引擎推断出{
时,您不必在PHP正则表达式中转义{
和}
,这意味着在所有上下文中都不需要转义}
)[{{}},两者都将匹配单个字符,该字符要么是{
要么是
,而不管您在character类中放入了多少{
和}
。我还通过将+
贪婪量词转换为所有格量词++
来增强其性能
详情:
-第1组开始:(
-2个连续的{{
s{
-0或更多序列:(?:[^{}]+++|(?R))*
-1个或多个符号,而不是[^{}]+
和{
(不允许回溯到此模式)}
-或|
-尝试匹配整个图案(?R)
-a}
子字符串}
-第1组结束)
preg_split
可以在正则表达式上拆分,同时保持文本匹配,因此非常适合此类任务
唯一的问题是,如果匹配项看起来是连续的或在字符串的开头/结尾,则空条目可能会爬入结果数组。因此,这里最好使用
PREG\u SPLIT\u NO\u empty
。我会使用这样的模式
$patt = '/(?P<open>\{\{)|(?P<body>[-0-9a-zA-Z._]+)|(?P<whitespace>\s+)|(?<opperators>and|or|==)|(?P<close>\}\})/'
preg_match_all( $patt, $text, $matches );
然后在循环中,您可以告诉match[0][0]
是打开的
标记,match[0][1]
是正文
匹配[0][3]
是另一种打开
等,通过跟踪打开和关闭标记,您可以计算出嵌套。它将告诉您什么是打开匹配体匹配关闭匹配运算符匹配等
你需要的每一件事,我都没有时间对解决方案进行全面的研究
一个简单的例子是,open
后接body
后接close
是一个变量。open
后接Andbody
和另一个open
是一个函数。
P
你也可以通过插入像这样的(?Pfunction\)
来添加额外的模式,其中的管道像/(?P\{{)(?Pfunction\)…
。然后你可以选择像function
foreach
block
等关键字。你有什么
我已经用这种方法编写了完整的模板系统
array (
0 =>
array (
0 => '{{',
1 => 'bar.function',
2 => '{{',
3 => 'demo.funtion',
4 => '{{',
5 => 'inner',
6 => '}}',
7 => ' ',
8 => '==',
9 => ' ',
10 => 'demo',
11 => '}}',
12 => ' ',
13 => 'and',
14 => ' ',
15 => '{{',
16 => 'bar',
17 => '}}',
18 => ' ',
19 => 'or',
20 => ' ',
21 => 'foo',
22 => '}}',
),
'open' =>
array (
0 => '{{',
1 => '',
2 => '{{',
3 => '',
4 => '{{',
5 => '',
6 => '',
7 => '',
8 => '',
9 => '',
10 => '',
11 => '',
12 => '',
13 => '',
14 => '',
15 => '{{',
16 => '',
17 => '',
18 => '',
19 => '',
20 => '',
21 => '',
22 => '',
),
),
'body' =>
array (
0 => '',
1 => 'bar.function',
2 => '',
3 => 'demo.funtion',
4 => '',
5 => 'inner',
6 => '',
....
)
)
[ 'open' => '\{\{', 'function' => 'function\.', .... ]
然后把它压缩成实际的正则表达式,让生活变得简单
$r = [];
foreach( $patt_array as $key=>$value ){
$r[] = '(?P<'.$key.'>'.$value.')';
}
$patt = '/'.implode('|', $r ).'/';
$r=[];
foreach($key=>$value的patt_数组){
$r[]='(?P'$value.');
}
$patt='/'.内爆('|',$r)。'/';
等等
如果您遵循。您所说的“捕获周围的文本”是什么意思?请澄清要求。为什么输出中的元素是空的?为什么最后的
{{foo
从更多的文本中分离出来?preg\u match\u all,而不是preg\u match。/\{{124;[-0-9a-zA-Z.+}/
这是3个模式,然后处理它们并跟踪开括号、闭括号匹配和正文匹配。然后可以进行嵌套。@ArtisticPhoenix对此表示抱歉,修复了预期结果。您介意进一步解释一下这个解决方案吗?它可以100%工作,但我不太清楚到底发生了什么。您是指PHP部分还是正则表达式部分?或者两者都有?所以正则表达式部分以及如何拆分是本例中的最佳解决方案。我想我现在已经澄清了这一切,如果还有任何不清楚的地方,请告知。