您的 eval 示例缺少返回值:
print eval("return $sItem;");
应该这样做:
$aData['test'] = 'foo';
$sItem = '$aData[\'test\']';
print eval("return $sItem;"); # foo
但不建议正常使用eval。你可以带着它进入地狱的厨房,因为 eval 是邪恶的。
而只是解析字符串并返回值:
$aData['test'] = 'foo';
$sItem = '$aData[\'test\']';
$r = sscanf($sItem, '$%[a-zA-Z][\'%[a-zA-Z]\']', $vName, $vKey);
if ($r === 2)
{
$result = ${$vName}[$vKey];
}
else
{
$result = NULL;
}
print $result; # foo
这也可以使用其他形式的正则表达式来完成。
由于您的语法非常接近 PHP 并且实际上是它的一个子集,如果您想在使用 eval 之前验证输入,您可以采取一些替代方法。该方法是检查 PHP 令牌并只允许一个子集。这不会验证字符串(例如语法和是否实际设置了变量),但会使其更加严格:
function validate_tokens($str, array $valid)
{
$vchk = array_flip($valid);
$tokens = token_get_all(sprintf('<?php %s', $str));
array_shift($tokens);
foreach($tokens as $token)
if (!isset($vchk[$token])) return false;
return true;
}
您只需为该函数提供一组有效标记。这些是 PHP 令牌,在您的情况下是:
T_LNUMBER (305) (probably)
T_VARIABLE (309)
T_CONSTANT_ENCAPSED_STRING (315)
然后你就可以使用它,它也可以使用更复杂的键:
$aData['test'] = 'foo';
$aData['te\\\'[]st']['more'] = 'bar';
$sItem = '$aData[\'test\']';
$vValue = NULL;
if (validate_tokens($sItem, array(309, 315, '[', ']')))
{
$vValue = eval("return $sItem;");
}
我在问题reliably convert string containing PHP array info to array的another answer中使用了这个。