【问题标题】:Regular expression for validating math equation用于验证数学方程的正则表达式
【发布时间】:2015-08-11 10:18:06
【问题描述】:

我正在尝试构建一个验证数学方程式的正则表达式。等式本身非常简单,我正在寻找一个英文可读的等式,稍后我将返回为真或假。一个例子就是这样。

((1 和 2) 或 3)

在此示例中,我将用真或假交换任何数字。我还将用“&&”替换“and”,用“||”替换“or”为了使用 PHP 运行方程。对此的回应最终要么是真的,要么是假的。

最终方程的示例如下所示:

((真 && 真) || 真)

这里有一些应该被认为是有效的例子。

(1 或 2 或 3)

((1 和 2 和 3) 或 (4 和 5))

所以,我的问题分为两部分。

  1. 是否可以创建一个正则表达式来验证所有可能的有效方程?对我来说,一大障碍是了解如何验证所有开头的“(”也有结尾的“)”。
  2. 在这种情况下,是否建议使用正则表达式来验证客户端?我已经能够使用 AJAX 和 PHP 来验证表达式了,我是不是想多了?

【问题讨论】:

  • recursive pattern 可以做到这一点。不过,这不是 JavaScript 中的一个选项。就其本身而言,这对评估表达式没有多大帮助。或者这真的只是关于数字和布尔运算符?
  • 使用 php 可以实现平衡的文本匹配。替换内容需要您知道什么是真/假。更有可能只需要直接替换 or/and into 符号即可。
  • @mario 在我们的应用程序中,数字代表一个变量,它将在 PHP 中返回 true|false。我们的目标是允许客户端对条件模式进行编辑,并在数字变为布尔值之前使用 angular 验证模式客户端。
  • @mario 澄清我们不想使用正则表达式评估表达式。我们希望在 PHP 中评估条件模式之前确保它是有效的。
  • JavaScript 实际上只有普通的旧正则表达式。 PHP 有正则表达式。因此,如果它们有效,您应该只进行 AJAX 调用以预先验证服务器端。顺便说一句,没有必要替换 andor,因为它们在 PHP 表达式中也是允许的。

标签: javascript php regex validation


【解决方案1】:

使用pumping lemma 可以很容易地证明您要验证的字符串属于不规则的language,因此无法使用正则表达式对其进行解析。 (实际上以证明这一点的方式使用了您无法匹配左括号和右括号甚至计算它们的事实-正如您在问题的第一部分中提到的那样)尽管某些正则表达式引擎可能会提供一些可用于解析的附加功能这(类似于递归模式)但不是 100% 符合正则表达式的正式定义。

您可以考虑自己解析括号并使用简单的正则表达式验证其中的表达式,或者您可以使用parse tree,类似于编译器所做的。

【讨论】:

  • @Joey 是的 :) 我在回答中提到了它
【解决方案2】:

这可以在 php 中完成(使用 PCRE 引擎)。
下面只是一个例子。
您可以注释掉错误检查,然后插入边界构造
围绕正则表达式使其最终通过/失败。

最大的问题不是递归,而是定义内容边界
状况。我已经为你简化了。这些检查必须
保持任何你如何做,状态,堆栈......,都是一样的。

(此正则表达式是使用 RegexFormat 6 构建和测试的)

示例输入:

 (((   (1 and 2 and 3) or (9) or ( ( 4 and 5)) and 5 ) and   7) )

测试输出:

 **  Grp 0 -  ( pos 0 , len 64 ) 
(((   (1 and 2 and 3) or (9) or ( ( 4 and 5)) and 5 ) and   7) )  
 **  Grp 1 -  ( pos 1 , len 62 ) 
((   (1 and 2 and 3) or (9) or ( ( 4 and 5)) and 5 ) and   7)   
 **  Grp 2 -  NULL 
 **  Grp 3 -  NULL 
 **  Grp 4 -  NULL 

正则表达式:
5/29 所有形式:

不允许使用空表单( )
不允许使用空表单) (
表单) and ( ok
表格) and 2 and ( ok
表格( 1 and 2 )ok
表格( 1 ) ok
表格) and 2 ) ok
表单( 1 and ( ok
形成( whitespace () whitespace ) ok

 # (?s)(?:\(((?!\s*\))(?&core))\)|\s*([()]))(?(DEFINE)(?<core>(?>(?&content)|\((?:(?!\s*\))(?&core))\)(?!\s*\())+)(?<content>(?>(?<=\))\s*(?:and|or)\s*(?=\()|(?<=\))\s*(?:(?:and|or)\s+\d+)+\s*(?:and|or)\s*(?=\()|(?<=\()\s*\d+(?:(?:\s+(?:and|or)\s+)?\d+)*\s*(?=\))|(?<=\))\s*(?:(?:and|or)\s+\d+)+\s*(?=\))|(?<=\()\s*(?:\d+\s+(?:and|or))+\s*(?=\()|\s+)))


 # //////////////////////////////////////////////////////
 # // The General Guide to 3-Part Recursive Parsing
 # // ----------------------------------------------
 # // Part 1. CONTENT
 # // Part 2. CORE
 # // Part 3. ERRORS

 (?s)                       # Dot-All modifier (used in a previous incarnation)

 (?:
      #           (                          # (1), Take off CONTENT (not used here)
      #                (?&content) 
      #           )
      #        |                           # OR

      \(                         # Open Paren's
      (                          # (1), parens CORE
           (?! \s* \) )               # Empty form '( )' not allowed
           (?&core) 
      )
      \)                         # Close Paren's
   |                           # OR
      \s* 
      (                          # (2), Unbalanced (delimeter) ERRORS
                                      # - Generally, on a whole parse, these
                                      #   are delimiter or content errors
           [()]                       
      )
 )

 # ///////////////////////
 # // Subroutines
 # // ---------------

 (?(DEFINE)

      # core
      (?<core>                   # (3)
           (?>
                (?&content) 
             |  
                \(                         # Open Paren's
                (?:
                     (?! \s* \) )               # Empty form '( )' not allowed
                     (?&core) 
                )
                \)                         # Close Paren's
                (?! \s* \( )               # Empty form ') (' not allowed
           )+
      )

      # content 
      (?<content>                # (4)
           (?>
                (?<= \) )                  # Form ') and ('
                \s* 
                (?: and | or )
                \s* 
                (?= \( )

             |  
                (?<= \) )                  # Form ') and 2 and ('
                \s* 
                (?:
                     (?: and | or )
                     \s+ 
                     \d+ 
                )+
                \s* 
                (?: and | or )
                \s* 
                (?= \( )

             |  
                (?<= \( )                  # Form '( 1 and 2 )'
                \s* 
                \d+ 
                (?:
                     (?:
                          \s+ 
                          (?: and | or )
                          \s+ 
                     )?
                     \d+ 
                )*
                \s* 
                (?= \) )

             |  
                (?<= \) )                  # Form ') and 2 )'
                \s* 
                (?:
                     (?: and | or )
                     \s+ 
                     \d+ 
                )+
                \s* 
                (?= \) )

             |  
                (?<= \( )                  # Form '( 1 and ('
                \s* 
                (?:

                     \d+ 
                     \s+ 
                     (?: and | or )
                )+
                \s* 
                (?= \( )

             |  
                \s+                        # Interstitial whitespace
                                           # '( here (' or ') here )'
           )
      )

 )

【讨论】:

  • 有一个错误,它也匹配((( (1 and 2 and 3) or (9) ( ( 4 and 5)) and 5 ) and 7) ) (9) ( ( 4 中的) ( 之间没有运算符
  • @revo - 修正:空表格 ') (' 不允许。还有吗?
  • 干得好,但不准确。我不是大规模输入测试人员,但为什么无法匹配此((( (1 and 2 and 3) or 9 or ( ( 4 and 5)) and 5 ) and 7) )9 没有括号。
  • @revo - 添加了表单 ) and 2 and ( 并列出了帖子中的所有表单。还有吗?
  • 我认为这涵盖了大部分表格。我在表格中很冗长。其中大部分包含冗余重叠。在做这种正则表达式时,一开始这是设计使然。确定所有部分后,下一步就是对其进行重构。但这可能有点棘手。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
  • 1970-01-01
相关资源
最近更新 更多