【问题标题】:Excluding all characters NOT in list AND NOT in a list of phrases排除所有不在列表中且不在短语列表中的字符
【发布时间】:2010-10-08 01:51:38
【问题描述】:

我正在尝试在 PHP 中创建一个函数来评估数学表达式——包括诸如 sin、cos 等函数。我的方法是删除短语中不是数字、数学运算符或数学函数,然后在 eval() 中使用该字符串。问题是我对正则表达式的了解不够,无法同时否定同一表达式中的字符和短语。

到目前为止,这就是我所拥有的:

$input = preg_replace("/[^0-9+\-.*\/()sincota]/", "", $input);

显然,sin、cos 和 tan 字符可以在输入表达式中以任何顺序使用(而不是允许使用短语 sin、cos 和 tan)。如果我进一步扩展此功能以包含更多字符和功能,则会带来更大的安全风险,因为恶意用户将能够通过与应用程序的巧妙交互来执行几乎任何 PHP 命令。

谁能告诉我如何修复我的正则表达式并消除这个问题?

【问题讨论】:

  • 嗯,大多数语言抛出语法错误而不是尝试最佳猜测是有原因的,这样就很疯狂(在某些情况下你必须是一个非常好的猜测者)。您的解决方案仍然是解析器,而不是正则表达式(真的,它并不难),瞧,不用担心执行“任何 PHP 命令”。 eval=-evil(大多数情况下...)
  • 谢谢,Wrikken。我已经十多年没有看到它并且(相当不方便地)忘记了它。我想我将不得不编写一个解析器,而不是仅仅试图摆脱一个快速的解决方案。

标签: php regex regex-negation


【解决方案1】:

我正在尝试在 将评估数学的 PHP 表达式——包括函数 如 sin、cos 等

我是否可以建议利用已投入到 PHPExcel 中的多年工作,其中已经包含一个公式解析器。

它包括cossin 和其他数百个。

否则,您可以寻找正匹配,而不是否定:

$matches = array();
preg_match_all("#([0-9,/\*()+\s\.-]|sin|cos)+#", 'sin(12) + cos(13.5/2) evddal * (4-1)', $matches);
echo implode('', $matches[0]);

/* output:
sin(12) + cos(13.5/2) * (4-1) 
*/

【讨论】:

    【解决方案2】:

    你可以试试这个:

    preg_replace("/(sin|cos|tan)?[^0-9+\\.*\/()-]/", "$1", $input);
    

    code on ideone.com

    但是,如果您尝试解析表达式来评估它,我建议您解析它,而不是简单地通过正则表达式模式传递它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-17
      • 2012-06-21
      • 1970-01-01
      • 2014-09-07
      • 2015-11-02
      • 2019-01-19
      • 2011-06-21
      相关资源
      最近更新 更多