我正在设计一个脚本并尝试在php中使用if构造而不使用eval 。
仍然不完整但是爆破,要做一个模板引擎,"如果"引擎的一部分。不允许赋值运算符,但我需要测试值而不允许使用php代码注入,正好不使用eval 它需要在变量之间进行单独操作以防止注入攻击
正则表达式必须捕获
[if:(a+b-c/d*e)|(x-y)&!(z%3=0)]
output
[elseif:('b'+'atman'='batman')]
output2
[elseif:('b'+'atman'='batman')]
output3
[elseif:('b'+'atman'='batman')]
output4
[else]
output5
[endif]
[if:(a+b-c/d*e)|(x-y)&!(z%3=0)]
output6
[else]
output7
[endif]
以下方法用于获取if,elseif,else和endif块以及条件语句:
$regex = '^\h*\[if:(.*)\]\R(?<if>(?:(?!\[elseif)[\s\S])+)\R^\h*\[elseif:(.*)\]\R(?<elseif>(?:(?!\[else)[\s\S])+)\R^\h*\[else.*\]\R(?<else>(?:(?!\[endif)[\s\S])+)\R^\[endif\]~xm';
请帮助选择elseif和其他。
然后使用条件语句,我可以通过以下方式获取操作:
$regex = '~([^\^=<>+\-%/!&|()*]+)([\^+\-%/!|&*])([^\^=<>+\-%/!&|()*]*)~';
然而,它只会配对它们,缺少每个第三个操作员......
感谢您的帮助。
答案 0 :(得分:7)
(编辑在底部添加了一个简单的if / elseif正文解析正则表达式)
使用PCRE,我认为这个正则表达式递归应该处理嵌套的
if/elseif/else/endif
构造。
在它的当前形式中,它是一个松散的解析,因为它没有定义
很好[if/elseif: body ]
的形式
例如,[if:
是起始分隔符构造,]
是结尾吗?
并且应该发生错误等等。如果需要严格解析,可以这样做
现在它基本上使用[if: body ]
作为开始分隔符
和[endif]
作为查找嵌套构造的结束分隔符。
此外,它将body
松散地定义为[^\]]*
,在严肃的解析中
情况,必须充实,以说明报价和东西
就像我说的那样,将它分开是可行的,但更多的是
参与其中。我在语言层面上做到了这一点,并不是一件轻而易举的事。
底部有一个宿主语言使用伪代码样本
语言递归演示了如何提取嵌套内容
正确。
正则表达式匹配核心的当前 outter shell。 核心的位置 是内部嵌套的内容。
每次对ParseCore()的调用都是在ParseCore()内部启动的 (来自 main()的初始调用除外。
由于范围界定似乎没有具体说明,我已经做出了可以看到的假设 评论中散落着。
if/elseif
正文中有一个占位符
然后可以解析 (operations)
部分,这部分实际上是第2部分
我还没有完成这项练习
注意 - 我会尝试这样做,但我今天没有时间。
如果您有任何疑问,请与我们联系。
(?s)(?:(?<Content>(?&_content))|\[elseif:(?<ElseIf_Body>(?&_ifbody)?)\]|(?<Else>(?&_else))|(?<Begin>\[if:(?<If_Body>(?&_ifbody)?)\])(?<Core>(?&_core)|)(?<End>\[endif\])|(?<Error>(?&_keyword)))(?(DEFINE)(?<_ifbody>(?>[^\]])+)(?<_core>(?>(?<_content>(?>(?!(?&_keyword)).)+)|(?(<_else>)(?!))(?<_else>(?>\[else\]))|(?(<_else>)(?!))(?>\[elseif:(?&_ifbody)?\])|(?>\[if:(?&_ifbody)?\])(?:(?=.)(?&_core)|)\[endif\])+)(?<_keyword>(?>\[(?:(?:if|elseif):(?&_ifbody)?|endif|else)\])))
(?s) # Dot-all modifier
# =====================
# Outter Scope
# ---------------
(?:
(?<Content> # (1), Non-keyword CONTENT
(?&_content)
)
| # OR,
# --------------
\[ elseif: # ELSE IF
(?<ElseIf_Body> # (2), else if body
(?&_ifbody)?
)
\]
| # OR
# --------------
(?<Else> # (3), ELSE
(?&_else)
)
| # OR
# --------------
(?<Begin> # (4), IF
\[ if:
(?<If_Body> # (5), if body
(?&_ifbody)?
)
\]
)
(?<Core> # (6), The CORE
(?&_core)
|
)
(?<End> # (7)
\[ endif \] # END IF
)
| # OR
# --------------
(?<Error> # (8), Unbalanced If, ElseIf, Else, or End
(?&_keyword)
)
)
# =====================
# Subroutines
# ---------------
(?(DEFINE)
# __ If Body ----------------------
(?<_ifbody> # (9)
(?> [^\]] )+
)
# __ Core -------------------------
(?<_core> # (10)
(?>
#
# __ Content ( non-keywords )
(?<_content> # (11)
(?>
(?! (?&_keyword) )
.
)+
)
|
#
# __ Else
# Guard: Only 1 'else'
# allowed in this core !!
(?(<_else>)
(?!)
)
(?<_else> # (12)
(?> \[ else \] )
)
|
#
# __ ElseIf
# Guard: Not Else before ElseIf
# allowed in this core !!
(?(<_else>)
(?!)
)
(?>
\[ elseif:
(?&_ifbody)?
\]
)
|
#
# IF (block start)
(?>
\[ if:
(?&_ifbody)?
\]
)
# Recurse core
(?:
(?= . )
(?&_core)
|
)
# END IF (block end)
\[ endif \]
)+
)
# __ Keyword ----------------------
(?<_keyword> # (13)
(?>
\[
(?:
(?: if | elseif )
: (?&_ifbody)?
| endif
| else
)
\]
)
)
)
主机语言伪代码
bool bStopOnError = false;
regex RxCore("....."); // Above regex ..
bool ParseCore( string sCore, int nLevel )
{
// Locals
bool bFoundError = false;
bool bBeforeElse = true;
match _matcher;
while ( search ( core, RxCore, _matcher ) )
{
// Content
if ( _matcher["Content"].matched == true )
// Print non-keyword content
print ( _matcher["Content"].str() );
// OR, Analyze content.
// If this 'content' has error's and wish to return.
// if ( bStopOnError )
// bFoundError = true;
else
// ElseIf
if ( _matcher["ElseIf_Body"].matched == true )
{
// Check if we are not in a recursion
if ( nLevel <= 0 )
{
// Report error, this 'elseif' is outside an 'if/endif' block
// ( note - will only occur when nLevel == 0 )
print ("\n>> Error, 'elseif' not in block, body = " + _matcher["ElseIf_Body"].str() + "\n";
// If this 'else' error will stop the process.
if ( bStopOnError == true )
bFoundError = true;
}
else
{
// Here, we are inside a core recursion.
// That means we have not hit an 'else' yet
// because all elseif's precede it.
// Print 'elseif'.
print ( "ElseIf: " );
// TBD - Body regex below
// Analyze the 'elseif' body.
// This is where it's body is parsed.
// Use body parsing (operations) regex on it.
string sElIfBody = _matcher["ElseIf_Body"].str() );
// If this 'elseif' body error will stop the process.
if ( bStopOnError == true )
bFoundError = true;
}
}
// Else
if ( _matcher["Else"].matched == true )
{
// Check if we are not in a recursion
if ( nLevel <= 0 )
{
// Report error, this 'else' is outside an 'if/endif' block
// ( note - will only occur when nLevel == 0 )
print ("\n>> Error, 'else' not in block\n";
// If this 'else' error will stop the process.
if ( bStopOnError == true )
bFoundError = true;
}
else
{
// Here, we are inside a core recursion.
// That means there can only be 1 'else' within
// the relative scope of a single core.
// Print 'else'.
print ( _matcher["Else"].str() );
// Set the state of 'else'.
bBeforeElse == false;
}
}
else
// Error ( will only occur when nLevel == 0 )
if ( _matcher["Error"].matched == true )
{
// Report error
print ("\n>> Error, unbalanced " + _matcher["Error"].str() + "\n";
// // If this unbalanced 'if/endif' error will stop the process.
if ( bStopOnError == true )
bFoundError = true;
}
else
// If/EndIf block
if ( _matcher["Begin"].matched == true )
{
// Print 'If'
print ( "If:" );
// Analyze 'if body' for error and wish to return.
// TBD - Body regex below.
// Analyze the 'if' body.
// This is where it's body is parsed.
// Use body parsing (operations) regex on it.
string sIfBody = _matcher["If_Body"].str() );
// If this 'if' body error will stop the process.
if ( bStopOnError == true )
bFoundError = true;
else
{
//////////////////////////////
// Recurse a new 'core'
bool bResult = ParseCore( _matcher["Core"].str(), nLevel+1 );
//////////////////////////////
// Check recursion result. See if we should unwind.
if ( bResult == false && bStopOnError == true )
bFoundError = true;
else
// Print 'end'
print ( "EndIf" );
}
}
else
{
// Reserved placeholder, won't get here at this time.
}
// Error-Return Check
if ( bFoundError == true && bStopOnError == true )
return false;
}
// Finished this core!! Return true.
return true;
}
///////////////////////////////
// Main
string strInitial = "...";
bool bResult = ParseCore( strInitial, 0 );
if ( bResult == false )
print ( "Parse terminated abnormally, check messages!\n" );
outter core 的输出样本匹配
请注意,当内核的匹配时,会有更多匹配。
** Grp 0 - ( pos 0 , len 211 )
[if:(a+b-c/d*e)|(x-y)&!(z%3=0)]
output
[elseif:('b'+'atman'='batman')]
output2
[elseif:('b'+'atman'='batman')]
output3
[elseif:('b'+'atman'='batman')]
output4
[else]
output5
[endif]
** Grp 1 [Content] - NULL
** Grp 2 [ElseIf_Body] - NULL
** Grp 3 [Else] - NULL
** Grp 4 [Begin] - ( pos 0 , len 31 )
[if:(a+b-c/d*e)|(x-y)&!(z%3=0)]
** Grp 5 [If_Body] - ( pos 4 , len 26 )
(a+b-c/d*e)|(x-y)&!(z%3=0)
** Grp 6 [Core] - ( pos 31 , len 173 )
output
[elseif:('b'+'atman'='batman')]
output2
[elseif:('b'+'atman'='batman')]
output3
[elseif:('b'+'atman'='batman')]
output4
[else]
output5
** Grp 7 [End] - ( pos 204 , len 7 )
[endif]
** Grp 8 [Error] - NULL
** Grp 9 [_ifbody] - NULL
** Grp 10 [_core] - NULL
** Grp 11 [_content] - NULL
** Grp 12 [_else] - NULL
** Grp 13 [_keyword] - NULL
-----------------------------
** Grp 0 - ( pos 211 , len 4 )
** Grp 1 [Content] - ( pos 211 , len 4 )
** Grp 2 [ElseIf_Body] - NULL
** Grp 3 [Else] - NULL
** Grp 4 [Begin] - NULL
** Grp 5 [If_Body] - NULL
** Grp 6 [Core] - NULL
** Grp 7 [End] - NULL
** Grp 8 [Error] - NULL
** Grp 9 [_ifbody] - NULL
** Grp 10 [_core] - NULL
** Grp 11 [_content] - NULL
** Grp 12 [_else] - NULL
** Grp 13 [_keyword] - NULL
-----------------------------
** Grp 0 - ( pos 215 , len 74 )
[if:(a+b-c/d*e)|(x-y)&!(z%3=0)]
output6
[else]
output7
[endif]
** Grp 1 [Content] - NULL
** Grp 2 [ElseIf_Body] - NULL
** Grp 3 [Else] - NULL
** Grp 4 [Begin] - ( pos 215 , len 31 )
[if:(a+b-c/d*e)|(x-y)&!(z%3=0)]
** Grp 5 [If_Body] - ( pos 219 , len 26 )
(a+b-c/d*e)|(x-y)&!(z%3=0)
** Grp 6 [Core] - ( pos 246 , len 36 )
output6
[else]
output7
** Grp 7 [End] - ( pos 282 , len 7 )
[endif]
** Grp 8 [Error] - NULL
** Grp 9 [_ifbody] - NULL
** Grp 10 [_core] - NULL
** Grp 11 [_content] - NULL
** Grp 12 [_else] - NULL
** Grp 13 [_keyword] - NULL
这是If / ElseIf Body 正则表达式
原始
(?|((?:\s*[^\^=<>+\-%/!&|()\[\]*\s]\s*)+)([\^+\-%/*=]+)(?=\s*[^\^=<>+\-%/!&|()\[\]*\s])|\G(?!^)(?<=[\^+\-%/*=])((?:\s*[^\^=<>+\-%/!&|()\[\]*\s]\s*)+)())
Stringed
'~(?|((?:\s*[^\^=<>+\-%/!&|()\[\]*\s]\s*)+)([\^+\-%/*=]+)(?=\s*[^\^=<>+\-%/!&|()\[\]*\s])|\G(?!^)(?<=[\^+\-%/*=])((?:\s*[^\^=<>+\-%/!&|()\[\]*\s]\s*)+)())~'
扩展
(?| # Branch Reset
( # (1 start), Operand
(?: \s* [^\^=<>+\-%/!&|()\[\]*\s] \s* )+
) # (1 end)
( [\^+\-%/*=]+ ) # (2), Forward Operator
(?= \s* [^\^=<>+\-%/!&|()\[\]*\s] )
|
\G
(?! ^ )
(?<= [\^+\-%/*=] )
( # (1 start), Last Operand
(?: \s* [^\^=<>+\-%/!&|()\[\]*\s] \s* )+
) # (1 end)
( ) # (2), Last-Empty Forward Operator
)
这是如何运作的:
假设非常简单的结构
这只会解析数学运算符/运算符的内容
它不会解析任何封闭的括号块,也不会解析任何逻辑或数学
两者之间的运营商
如果需要,提前解析所有括号块,即\( [^)* \)
或
类似。或者拆分像|
这样的逻辑运算符。
正文正则表达式使用分支重置来获取操作数/运算符序列 它总是匹配两件事 组1包含操作数,组2包含操作符。
如果组2为空,则组1是序列中的 last 操作数。
有效运算符为^ + - % / * =
包括等于=
,因为它分隔了操作集合
并且可以被注意为分离。
关于这个身体正则表达式的结论是它非常简单和
仅适合简单使用。涉及更复杂的事情
这不是要走的路。
输入/输出样本1:
(a+b-c/d*e)
** Grp 1 - ( pos 1 , len 1 )
a
** Grp 2 - ( pos 2 , len 1 )
+
------------
** Grp 1 - ( pos 3 , len 1 )
b
** Grp 2 - ( pos 4 , len 1 )
-
------------
** Grp 1 - ( pos 5 , len 1 )
c
** Grp 2 - ( pos 6 , len 1 )
/
------------
** Grp 1 - ( pos 7 , len 1 )
d
** Grp 2 - ( pos 8 , len 1 )
*
------------
** Grp 1 - ( pos 9 , len 1 )
e
** Grp 2 - ( pos 10 , len 0 ) EMPTY
输入/输出样本2:
('b'+'atman'='batman')
** Grp 1 - ( pos 1 , len 3 )
'b'
** Grp 2 - ( pos 4 , len 1 )
+
------------
** Grp 1 - ( pos 5 , len 7 )
'atman'
** Grp 2 - ( pos 12 , len 1 )
=
------------
** Grp 1 - ( pos 13 , len 8 )
'batman'
** Grp 2 - ( pos 21 , len 0 ) EMPTY
答案 1 :(得分:3)
你在这里有不同的可能性。
^\h*\[if.*\]\R # if in the first line
(?<if>(?:(?!\[elseif)[\s\S])+)\R # output
^\h*\[elseif.*\]\R # elseif
(?<elseif>(?:(?!\[else)[\s\S])+)\R # output
^\h*\[else.*\]\R # elseif
(?<else>(?:(?!\[endif)[\s\S])+)\R # output
^\[endif\]
之后,您有三个已命名的已捕获组(if
,elseif
和else
)。
见a demo for this one on regex101.com。
在PHP
中,这将是:
<?php
$code = <<<EOF
[if:(a+b-c/d*e)|(x-y)&!(z%3=0)]
output
[elseif:('b'+'atman'='batman')]
output2
out as well
[else]
output3
some other output here
[endif]
EOF;
$regex = '~
^\h*\[if.*\]\R # if in the first line
(?<if>(?:(?!\[elseif)[\s\S])+)\R # output
^\h*\[elseif.*\]\R # elseif
(?<elseif>(?:(?!\[else)[\s\S])+)\R # output
^\h*\[else.*\]\R # elseif
(?<else>(?:(?!\[endif)[\s\S])+)\R # output
^\[endif\]
~xm';
preg_match_all($regex, $code, $parts);
print_r($parts);
?>
<小时/>
也许最好略读线条并寻找[if...]
,在字符串中捕获任何高达[elseif...]
的内容,然后将它们粘合在一起。
<?php
$code = <<<EOF
[if:(a+b-c/d*e)|(x-y)&!(z%3=0)]
output
[elseif:('b'+'atman'='batman')]
output2
out as well
[else]
output3
some other output here
[endif]
EOF;
// functions, shamelessly copied from http://stackoverflow.com/questions/834303/startswith-and-endswith-functions-in-php
function startsWith($haystack, $needle) {
// search backwards starting from haystack length characters from the end
return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false;
}
function endsWith($haystack, $needle) {
// search forward starting from end minus needle length characters
return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== false);
}
$code = explode("\n", $code);
$buffer = array("if" => null, "elseif" => null, "else" => null);
$pointer = false;
for ($i=0;$i<count($code);$i++) {
$save = true;
if (startsWith($code[$i], "[if")) {$pointer = "if"; $save = false;}
elseif (startsWith($code[$i], "[elseif")) {$pointer = "elseif"; $save = false; }
elseif (startsWith($code[$i], "[else")) {$pointer = "else"; $save = false; }
elseif (startsWith($code[$i], "[endif")) {$pointer = false; $save = false; }
if ($pointer && $save) $buffer[$pointer] .= $code[$i] . "\n";
}
print_r($buffer);
?>