Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/235.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_Preg Match All - Fatal编程技术网

Php 按正则表达式拆分自定义条件

Php 按正则表达式拆分自定义条件,php,regex,preg-match-all,Php,Regex,Preg Match All,我正忙于编写一个后端模块,用户可以在其中创建自己的条件/规则。现在我想把一个条件分成几个部分 例如: 条件:{variable}>100 条件:{variable}=={anotherVariable}或{var}{variable}=={anotherVariable} [1] =>或 [2] =>{var}和 [2] =>{var}和 [4] =>{variable}==某个字符串 ) 之后,我必须将比较分为三部分: 比较:{variable}=={anotherVariable} //所

我正忙于编写一个后端模块,用户可以在其中创建自己的条件/规则。现在我想把一个条件分成几个部分

例如:

条件:{variable}>100

条件:{variable}=={anotherVariable}或{var}{variable}=={anotherVariable} [1] =>或 [2] =>{var}和 [2] =>{var}和 [4] =>{variable}==某个字符串 ) 之后,我必须将比较分为三部分:

比较:{variable}=={anotherVariable}

//所需的输出
//允许的比较运算符为:==,!=,>,>=,==/比较运算符
[2] =>{anotherVariable}//比较
)

我现在在正则表达式上苦苦挣扎了好几个小时,但没有得到所需的输出。

为了让它更简单,我假设字符串在双引号之间

模式的第一部分使用命名的子模式定义(
(?(DEFINE)…)
)所需的元素。首先是简单元素(比较运算符、布尔运算符、操作数),然后是更复杂的元素(原子条件、条件、检查)。每个子模式都可以和其他子模式以及子模式本身一起定义

一旦定义部分关闭,主模式开始并在每次迭代中捕获名为capture的“标记”内的三个可能元素:布尔运算符、原子条件(即最可能的基本条件)或括号内的整个条件

要成功,主模式必须通过两个入口点中的一个,第一个(仅使用一次)是子模式
\g
。此子模式确保整个字符串从头到尾格式良好,并且由于它是以
\a
开头的零宽度断言,因此强制标记搜索从字符串的开头开始。第二个输入点是
(?!\A)\G
,表示“不在字符串开头,与前一个匹配项相邻”。此条目用于所有其他匹配项

名为capture的
\g
仅在此处由递归函数使用。如果捕获存在,则标记是括号内的一个完整条件,需要重新分析以生成数组

define('PATTERN', <<<'EOD'
~
(?(DEFINE)
  (?<comp_op> [=!]= | >=? | <[=>]? )
  (?<bool_op> OR | AND )
  (?<operand> { \w+ } | -?\d+ | "[^"]+" ) # you can improve the " pattern

  (?<at_cond> \g<operand> \s+ \g<comp_op> \s+ \g<operand> ) # atomic cond
  (?<cond> \g<at_cond> (?> \s+ \g<bool_op> \s+ \g<cond> )* | \( \g<cond> \) )
  (?<check> (?= \A \s* \g<cond> \s* \z ) ) # checks the whole string format
)

(?: \g<check> \s* | (?!\A)\G \s+)
(?| (?<token>\g<bool_op>) | (\g<at_cond>) | \( (\g<cond>) )
(?<par> \) )? # only to test if a recursion is needed
~x
EOD
);

function getTokens ($str) {
    if (preg_match_all(PATTERN, $str, $matches)) {
        $tokens = array(); 
        foreach ($matches['token'] as $k=>$token) {
            $tokens[] = ($matches['par'][$k]) ? getTokens($token) : $token;
        }
        return $tokens;
    }
    return false;
}

$testset = array(
    '{variable} > 100',
    '{variable} == {zogabu} OR {buga} <= 10',
    '{meuh} == {zo} AND ({meuh} <= 10 OR {zomeuh} == "GABUZO")',
    '{BU} > 3 AND ({ga} == "ZO" OR ({bu} == "GA" AND {meuh} != "GA"))' );

foreach($testset as $test_string) {
    $result = getTokens($test_string);    
    echo "\ntest_string: $test_string\n" . print_r($result, true);
}
define('PATTERN',$token){
$tokens[]=($matches['par'][$k])?getTokens($token):$token;
}
归还$tokens;
}
返回false;
}
$testset=array(
“{variable}>100”,

{variable}={zogabu}或{buga}它们可以嵌套
?@anubhava是的,这将是功能的极大提升,但我在数组中没有一个很好的答案。它应该用{var}>10和({var2}==某物或{var3}==某物)来做一些事情。正则表达式可以让这两者之间的一切都存在吗()在一个新数组中?正则表达式不是这个的合适工具。你需要构建你的自定义解析器。(不解析嵌套的)。在我看来,这不是一个可以单独用正则表达式解决的问题。在我看来,你还需要添加一些编程逻辑。
// desired output
Array
(
    [0] => {variable} == {anotherVariable}
    [1] => OR
    [2] => {var} <= 10
)
// desired output
Array
(
    [0] => {variable} == {anotherVariable}
    [1] => AND
    [2] => {var} <= 10
    [3] => AND
    [4] => {variable} == some string
)
// desired output
// allowed comparison operators are: ==, !=, >, >=, <, <=, <>
Array
(
    [0] => {variable}               // comparison
    [1] => ==                       // comparision operator
    [2] => {anotherVariable}        // comparison
)
define('PATTERN', <<<'EOD'
~
(?(DEFINE)
  (?<comp_op> [=!]= | >=? | <[=>]? )
  (?<bool_op> OR | AND )
  (?<operand> { \w+ } | -?\d+ | "[^"]+" ) # you can improve the " pattern

  (?<at_cond> \g<operand> \s+ \g<comp_op> \s+ \g<operand> ) # atomic cond
  (?<cond> \g<at_cond> (?> \s+ \g<bool_op> \s+ \g<cond> )* | \( \g<cond> \) )
  (?<check> (?= \A \s* \g<cond> \s* \z ) ) # checks the whole string format
)

(?: \g<check> \s* | (?!\A)\G \s+)
(?| (?<token>\g<bool_op>) | (\g<at_cond>) | \( (\g<cond>) )
(?<par> \) )? # only to test if a recursion is needed
~x
EOD
);

function getTokens ($str) {
    if (preg_match_all(PATTERN, $str, $matches)) {
        $tokens = array(); 
        foreach ($matches['token'] as $k=>$token) {
            $tokens[] = ($matches['par'][$k]) ? getTokens($token) : $token;
        }
        return $tokens;
    }
    return false;
}

$testset = array(
    '{variable} > 100',
    '{variable} == {zogabu} OR {buga} <= 10',
    '{meuh} == {zo} AND ({meuh} <= 10 OR {zomeuh} == "GABUZO")',
    '{BU} > 3 AND ({ga} == "ZO" OR ({bu} == "GA" AND {meuh} != "GA"))' );

foreach($testset as $test_string) {
    $result = getTokens($test_string);    
    echo "\ntest_string: $test_string\n" . print_r($result, true);
}