【问题标题】:Evaluate a math expression with regex使用正则表达式评估数学表达式
【发布时间】:2016-02-12 21:15:27
【问题描述】:

我需要创建一个方法来接收包含数学表达式的字符串,并且必须:

  • 先验证一下。
  • 返回问题/问题(如果存在)(例如,类似这样的内容:4+3+4/04+4+(((2-2*4)-)。
  • 如果一切正常,解决它并返回最终值。

到目前为止我所做的是:

  • 我知道eval 完全符合我的需要,但是它存在SQL 注入等问题。
  • 我发现了正则表达式。

我真的不知道设计这种方法的最佳方式,以使其安全并使用括号、运算符和数字。我在想的是使用正则表达式来检查初始字符串是否等于匹配的字符串。如果是,我正在考虑使用eval 来计算最终值。您认为这是正确的做法吗?

不确定我应该做什么,我写道:

def math_eval(expression)
   a = /\(* \s* \d+ \s* (( [-\+\*\/] \s* \d+ \)* \s* ) | ( [-\+\*\/] \s* \(* \s* \d+ \s* ))+/
   puts "Let's Go"
   puts a.match(expression)
end

math_eval("lets see if this works 1/ 2 * 3 hello world")

这是返回:

Let's Go
Empty string

我看过 Stack Overflow 的帖子

/\(* \s* \d+ \s* (( [-\+\*\/] \s* \d+ \)* \s* ) | ( [-\+\*\/] \s* \(* \s* \d+ \s* ))+/

将是正确的正则表达式过滤器。

我做错了什么?我应该改变我的方法吗?

编辑:我采用了不同的方法。您认为以下方法安全吗?

class FormulaCalculator

    def formula_validator(string_formula)
        extracted_formula = string_formula.tr('Ⓐⓐ⒜AaẠạÅåÄäẢảḀḁẤấẦầẨẩȂȃẪẫẬậẮắẰằẲẳẴẵẶặĀāĄąȀȁǺǻȦȧÁáǞǟǍǎÀàÃãǠǡÂâȺⱥÆæǢǣǼǽⱯꜲꜳꜸꜹꜺꜻⱭ℀⅍℁ªⒷⓑ⒝BbḂḃḄḅḆḇƁɃƀƂƃƄƅℬⒸⓒ⒞CcḈḉĆćĈĉĊċČčÇçƇƈȻȼℂ℃ƆꜾꜿℭ℅℆℄Ⓓⓓ⒟DdḊḋḌḍḎḏḐḑḒḓĎďƊƋƌƉĐđȡDZDzdzDŽDždžȸⅅⅆⒺⓔ⒠EeḔḕḖḗḘḙḚḛḜḝẸẹẺẻẾếẼẽỀềỂểỄễỆệĒēĔĕĖėĘęĚěÈèÉéÊêËëȄȅȨȩȆȇƎⱻɆɇƏǝℰⱸℯ℮ℇƐⒻⓕ⒡FfḞḟƑƒꜰℲⅎꟻℱ℻Ⓖⓖ⒢GgƓḠḡĜĝĞğĠġǤǥǦǧǴℊ⅁ǵĢģⒽⓗ⒣HhḢḣḤḥḦḧḨḩḪḫĤĥȞȟĦħⱧⱨꜦℍǶẖℏℎℋℌꜧⒾⓘ⒤IiḬḭḮḯIJijÍíÌìÎîÏïĨĩĪīĬĭĮįǏǐıƚỺⅈⅉℹℑℐⒿⓙ⒥JjĴĵɈɉȷⱼǰⓀⓚ⒦KkḰḱḲḳḴḵĶķƘƙꝀꝁꝂꝃꝄꝅǨǩⱩⱪĸⓁⓛ⒧LlḶḷḸḹḺḻḼḽĹĺĻļĽľĿŀŁłỈỉⱠⱡȽꝉꝈⱢLJLjljỊİịꞁ⅃⅂ȈȉȊȋℓℒⓂⓜ⒨MmḾḿṀṁṂṃꟿꟽⱮƜℳⓃⓝ⒩NnṄṅṆṇṈṉṊṋŃńŅņŇňǸǹÑñȠƞŊŋƝʼnNJNjnjȵℕ№Ⓞⓞ⒪OoÖöṎṏṌṍṐṑṒṓȪȫȬȭȮȯȰȱǪǫǬǭỌọỎỏỐốỒồỔổỖỗỘộỚớỜờỞởỠỡỢợƠơŌōŎŏŐőÒòÓóÔôÕõǑǒȌȍȎȏŒœØøǾǿꝊꝎꝏ⍥⍤ℴⓅⓟ⒫℗PpṔṕṖṗƤƥⱣℙǷꟼ℘Ⓠⓠ⒬QqɊɋℚ℺ȹⓇⓡ⒭RrŔŕŖŗŘřṘṙṚṛṜṝṞṟȐȑȒȓɌɍƦꝚꝛⱤ℞ℜℛ℟ℝⓈⓢ⒮SsṠṡṢṣṤṥṦṧṨṩŚśŜŝŞşŠšȘșȿꜱƧƨϨϩẞßẛẜẝ℠Ⓣⓣ⒯TtṪṫṬṭṮṯṰṱŢţŤťŦŧȚțȾⱦƬƮƫƭẗȶ℡™Ⓤⓤ⒰UuṲṳṴṵṶṷṸṹṺṻỦủỤụỨứỪừỬửỮữỰựŨũŪūŬŭŮůŰűǙǚǗǘǛǜŲųǓǔȔȕÛûȖȗÙùÚúÜüƯưɄƲƱⓋⓥ⒱VvṼṽṾṿɅ℣ỼⱱⱴⱽⓌⓦ⒲WwẀẁẂẃẄẅẆẇẈẉŴŵⱲⱳϢϣẘⓍⓧ⒳XxẊẋẌẍℵ×Ⓨⓨ⒴yYẎẏỾỿỲỳỴỵỶỷỸỹŶŷƳƴŸÿÝýɎɏȲȳƔẙ⅄ℽⓏⓩ⒵ZzẐẑẒẓẔẕŹźŻżŽžȤȥⱫⱬƵƶɀℨℤ', '')
     if string_formula = extracted_formula
            return true
        else
            return false
        end
     end

     def formula_evaluation(string_formula)
        if formula_validator(string_formula) == true
            return eval(string_formula)
        end
     rescue Exception => e
        puts e
     end
 end

【问题讨论】:

  • 欢迎来到 Stack Overflow。您是在向我们征求意见或答案吗?类似“SQL 注入”的情况是用户输入表达式而您盲目地执行它。如果您的表达式是由您的代码生成的或来自已知的良好来源,那么您是安全的。您的正则表达式将不起作用,因为空格在模式中很重要。有一面旗帜让他们变得无足轻重。你可以弄清楚它是什么。
  • 检查表达式的语法正确性通常通过将表达式转换为前缀或后缀形式来完成。不确定正则表达式是正确的工具。如果您不想重新发明*,似乎还有一个 Ruby 库来构建解析器 - github.com/nathansobo/treetop
  • 大家好,谢谢大家。我最终做了一些更简单的事情。

标签: ruby regex string math


【解决方案1】:

您不能使用正则表达式来识别格式正确的数学表达式。

理论上,正则表达式可以与有限状态自动机匹配,而这种自动机的有限状态数无法跟踪它可能遇到的无限数量的左括号。正确匹配括号的语言不是regular language

您可以做的是使用正则表达式标记字符串,然后解析标记流。

另见Regular expression for math operations with parentheses

【讨论】: