Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 匹配不在花括号内的文本,同时捕获后面的括号_Php_Regex - Fatal编程技术网

Php 匹配不在花括号内的文本,同时捕获后面的括号

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

我的情况需要递归,我能够以我需要的方式匹配花括号中的内容,但我无法捕获周围的文本

这就是示例文本:

这是foo{{foo}}和{bar.function({{demo.function({{inner}}==“demo”)}}和{{bar}或“foo”)}更多的文本{{foo

我需要我的结果如下所示:

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
    • (?:[^{}]+++|(?R))*
      -0或更多序列:
      • [^{}]+
        -1个或多个符号,而不是
        {
        }
        (不允许回溯到此模式)
      • |
        -或
      • (?R)
        -尝试匹配整个图案
  • }
    -a
    }
    子字符串
  • -第1组结束
PHP部分:

当只使用一种标记类型对字符串进行标记时,很容易使用拆分方法。由于PHP中的
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
后接And
body
和另一个
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部分还是正则表达式部分?或者两者都有?所以正则表达式部分以及如何拆分是本例中的最佳解决方案。我想我现在已经澄清了这一切,如果还有任何不清楚的地方,请告知。