PHP-替换字符并计算

时间:2019-02-24 20:53:41

标签: php

我得到了一个包含要替换为整数并计算的特定字符的公式字符串。该公式来自不同的用户,整数值来自数据库。

示例:

$formula = 'x/100';
$formula = '(5*(x+20))';
...

我得到一个个人数字,比如说34,并将其用作公式中的x。

我该如何使用PHP?找不到解决方案。

我尝试使用用户功能,但不幸的是,这似乎不起作用。

$number  = 34;
$formula = str_replace('x', $number, $formula);

$result = function () use ($formula) {
  echo round($formula);
};

echo $example();

结果为“ 34”,而不是“ 34/100”。

1 个答案:

答案 0 :(得分:1)

处理用户编写的纯文本公式需要大量工作,以解析给定的表达式,标记化,验证并最终通过根据需要替换占位符来执行。 (在这种情况下,x是一个占位符。)

从编程的角度来看,这种目标非常适合进入Abstract Syntax TreesLexical Analysis的世界。就个人而言,在尝试构建复杂的东西之前,我会先看一下doctrine/lexer。它可以减少您实现很多目标所需的总体工作。 Doctrine ORM使用 doctrine / lexer 来理解用户编写的DQL查询。

我不建议使用基于 str_replace preg_replace eval()的hacky解决方案,因为这可能会导致严重的安全问题。用户可以以论坛和开发人员的身份编写任何废话,您始终需要首先进行验证。如果没有用于理解给定公式结构的规则列表,则验证几乎是不可能的。

更新

为证明它的缺陷和危险,下面是一个相对安全的eval方案。

  

下面的废话只是为了演示eval()的问题,而不是问题的实际解决方案。不要使用它!

$formula = '(12+5) * 2 / x';
/**
 * Strip out everything other than a dot, arithmetic operators, paranthesis 
 * and the letter x to use as placeholder from given formula
 */
$filteredExpression = preg_replace('/[^\(\)\+\-\.\*\/\d+\.x]/', '', $formula);
$actualFormula = str_replace('x', 1, $filteredExpression);
$result = eval('return ' . $actualFormula . ';');

此示例部分可行,但仍然存在以下重要问题:

  • 用户可以添加超出要求的括号,或者他们忘记关闭左括号。这将导致解析错误:
      

    PHP解析错误:语法错误,意外的')'..

  • 用户可以尝试将任意数字除以零:
      

    PHP警告:除以零英寸。

  • 用户可以尝试使用逗号,代替点.作为十进制占位符。这可能会导致错误/意外的结果。
  • 用户可以有意或无意地在任何地方引入exponentiation**)或递增/递减++--运算符,这也可能最终导致错误/意外的结果。 (更复杂的正则表达式可能对此有所帮助,但不值得)
  • 企业(或您)将来可能希望支持一些简单的功能,例如SUM()AVG()MIN()MAX()等。现在该怎么办?甚至其中一些是部分可实现的,完成这一工作的代码在此之后很快就会变得一团糟。