Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.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 Regex匹配一组字符,但仅当特定字符未分组时_Php_Regex_Preg Match All_Preg Split - Fatal编程技术网

Php Regex匹配一组字符,但仅当特定字符未分组时

Php Regex匹配一组字符,但仅当特定字符未分组时,php,regex,preg-match-all,preg-split,Php,Regex,Preg Match All,Preg Split,这是一个棘手的问题,我有一个字符串: This is some text with a {%TAG IN IT%} and some more text then {%ANOTHER TAG%} with some more text at the end. 我有一个正则表达式来匹配标记: ({%\w+[\w =!:;,\.\$%"'#\?\-\+\{}]*%}) 将起始标记与任何字母数字字符后跟任何数量的其他ansi字符相匹配(上述正则表达式中指定的示例集) 但是(在PHP中,使用“pre

这是一个棘手的问题,我有一个字符串:

This is some text with a {%TAG IN IT%} and some more text then {%ANOTHER TAG%} with some more text at the end.
我有一个正则表达式来匹配标记:

({%\w+[\w =!:;,\.\$%"'#\?\-\+\{}]*%})
将起始标记与任何字母数字字符后跟任何数量的其他ansi字符相匹配(上述正则表达式中指定的示例集)

但是(在PHP中,使用“preg_match_all”“preg_split”至少)集合同时包含百分比(%)和大括号({}),这意味着如果同一行上有两个标记,则正则表达式匹配过多

e、 g,在给出的示例中,以下匹配:

{%TAG IN IT%} and some more text then {%ANOTHER TAG%}
正如您所看到的,%}…{%是匹配的。因此,我需要的是允许使用“%”,但后面跟着“}”

我尝试了非reedy匹配和负前瞻,但负前瞻在字符集中不起作用(即[\w..]*集中的所有内容)


我卡住了

您可以使用alternation来实现这一点:

/\{%(?:[^%]|%(?!}))*%\}/
它匹配的字符不是
%
,或者后面没有
}
(使用向前看)的字符

输出:

Array
(
    [0] => {%tag with % and } inside%}
    [1] => {%ANOTHER TAG%}
)

对regexp稍加修改即可(只需添加问号即可使其不贪婪)-



所以
%
}
都可以作为有效的标记值出现?%和}都可以作为有效字符出现在标记中(json值可以存储在其中),但是,%}不能在一起。。。这是标记的结尾:)是,但如果
%
位于子字符串中的最后一个位置,则模式将匹配%%,并继续到下一个
%}
或失败。是,这几乎就是我需要的,尽管不允许使用“任何字符”。仅在集合中指定的字符…:-(在处理匹配项时,无论出于何种原因,您都可以选择忽略无效的条目。非常好-感谢您快速而简单的响应!
Array
(
    [0] => {%tag with % and } inside%}
    [1] => {%ANOTHER TAG%}
)
<?php
    $input = "This is some text with a {%TAG % }IT%%} and some more text then {%ANOTHER TAG%} with some more text at the end.";
    $regexp = "/{%\w+[\w =!:;,\.\$%\"'#\?\-\+\{}]*?%}/";
    //                                            ^ Notice this
    if(preg_match_all($regexp, $input, $matches, PREG_SET_ORDER)) {
        foreach($matches as $match) {
            var_dump($match);
            echo "\r\n";
        }
        unset($match);
    }
    /*
        Outputs:
        array
          0 => string '{%TAG % }IT%%}' (length=14)
        array
          0 => string '{%ANOTHER TAG%}' (length=15)
    */
?>