【问题标题】:Using regular expression for validating data is correct or not?使用正则表达式验证数据是否正确?
【发布时间】:2010-07-18 07:29:38
【问题描述】:

我一直在寻找一些建议不要使用正则表达式来验证用户数据的文章和帖子。我不确定所有的事情,但我通常会在电子邮件地址验证的情况下找到它。

所以我想弄清楚使用正则表达式验证用户输入是否好?如果它很好,那么验证电子邮件地址有什么坏处?

编辑:

所以我们可以说,对于数据类型的基本主要验证,我们可以使用正则表达式,它很好,而对于完整验证,我们需要将它与另一个解析器结合起来。

对于一般用途的电子邮件验证的第二部分,我们可以使用它,但根据标准它是不合适的。是吗?

现在在选择正确答案时感到困惑

【问题讨论】:

    标签: regex validation logic


    【解决方案1】:

    这很好,因为您可以使用正则表达式以简单的方式表达和测试复杂的模式。

    这很糟糕,因为正则表达式可能很复杂,而且你可能会做错很多事情。


    编辑    好吧,好的。这里有一些真正的建议:首先确保可以使用正则表达式来表达预期的有效值。即有效值的语言是regular language。否则你根本不能使用正则表达式(或者至少不能只使用正则表达式)!

    既然我们知道什么可以使用正则表达式进行验证,我们应该讨论什么可以使用正则表达式进行验证。如果我们以电子邮件地址为例(像许多其他人一样),我们应该知道valid e-mail address 可能是什么样的(参见 RFC 5322):

    addr-spec       =   local-part "@" domain
    local-part      =   dot-atom / quoted-string / obs-local-part
    domain          =   dot-atom / domain-literal / obs-domain
    domain-literal  =   [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
    dtext           =   %d33-90 /          ; Printable US-ASCII
                        %d94-126 /         ;  characters not including
                        obs-dtext          ;  "[", "]", or "\"
    

    这里我们看到 local-part 可能包含一个 quoted-string,其中可能包含任何可打印的 US-ASCII 字符(不包括 \" ",但包括@)。因此,如果我们希望根据 RFC 5322 允许地址,则仅测试电子邮件地址是否仅包含一个 @ 是不够的。

    另一方面,如果我们希望根据 RFC 5322 允许任何有效的电子邮件地址,我们也将允许在大多数情况下可能不存在或毫无意义的地址(例如 ""@localhost)。

    【讨论】:

    • 那么最好使用正则表达式进行数据验证的第一步,然后使用另一个解析器进行完整验证
    • @KoolKabin:使用正则表达式只能满足句法测试,而不是语义测试。 语法有效表示符合标准。 语义有效意味着它在你想使用它的领域/领域是有意义的。
    【解决方案2】:

    您的问题似乎有两部分:(1)使用正则表达式进行数据验证不好,(2)使用它们验证电子邮件地址不好?

    Re (1),这真的取决于情况。在许多情况下,正则表达式足以验证用户输入。例如,验证用户名是否只有字母数字字符。当输入可能传递给数据库查询或 eval() 语句之类的东西时,一组正则表达式可能不够用。在这些情况下,可能存在无法使用正则表达式处理的递归等语言结构,更一般地说,您需要对目标语言了解很多的东西来进行验证(和清理)。

    在大多数情况下,您会希望对输入进行转义,使其成为目标语言中的无害字符串。

    如果您要验证代码的正确性,您将需要一个成熟的解析器。解析器可能会使用正则表达式,但通常解析器会使用其他东西来完成繁重的工作。

    【讨论】:

    • 我同意将我的问题分成两部分。那么,最好使用正则表达式进行数据验证的第一步,然后使用另一个解析器进行完整验证。那么电子邮件的第二部分是什么?
    • 我对验证电子邮件地址的情况知之甚少,无法以一种或另一种方式说出来。我的感觉是它足够复杂,您可能想要使用现有的库,但我也看到了一些尝试验证电子邮件地址的正则表达式,这些可能就足够了。如果您需要高度的正确性,我会熟悉相关的 RFC。这可能会变得更加困难,因为并非所有电子邮件提供商都可能要求严格有效的电子邮件地址。只是一些想法——其他人会在这里知道更多。
    【解决方案3】:

    正则表达式之所以不好,有以下三个原因:

    1. 它们会变得非常复杂,最终无法维护。很容易出错。
    2. 某些类型的文本根本无法用正则表达式解析(例如HTML)。基本上,任何具有嵌套模式的东西都不能用正则表达式解析。例如,您将无法使用正则表达式解析编程语言。
    3. 根据您使用的文本类型,如果您只编写自己的代码来解析它可能会更容易和更清晰。

    但是,如果这些对于您正在使用的任何东西都不是问题,那么使用正则表达式就没有错。我想说验证电子邮件地址是对正则表达式的一种很好的使用。

    【讨论】:

      【解决方案4】:

      正则表达式和其他任何工具一样都是一种工具,尽管它非常强大。

      它们非常强大,以至于使用它们的人往往会遇到所有看起来都像钉子的问题(当你有一把锤子时)。这导致它们被用于另一种方法更冗长但更有效且更易于维护的情况。

      在电子邮件地址的特定情况下,这里的主要问题是,有大量的正则表达式声称可以验证电子邮件地址的语法,但是却充满了导致误报的问题。

      他们的主要问题包括:

      • 不允许在地址的前半部分使用加号(尽管它们比较常见)
      • 将 TLD 限制为三个字符(这会屏蔽 .museum TLD)
      • 将 TLD 限制为两个字符的国家/地区代码 TLD 或特定 TLD 列表(因此,每当有新 TLD 发挥作用时,它就会强制更新 - 猜猜什么永远不会发生?)

      电子邮件地址是如此复杂,以至于正则表达式不应该真正尝试做更多的事情:

      1. 不包含@ 的内容
      2. @
      3. 不包含@ 的内容
      4. 一个.
      5. 不包含@ 的内容

      【讨论】:

      • 电子邮件地址的“本地部分”实际上可以包含@符号,只是不太常见。
      【解决方案5】:

      对于电子邮件地址,最好使用正则表达式。它适用于大多数情况。

      一般来说:您应该使用正则表达式验证任何可以表示为regular language的内容

      【讨论】:

      • 这取决于您使用的正则表达式。我见过太多的误报,无法鼓励人们使用正则表达式来检查电子邮件地址(至少没有很多的附带条件)。
      • “它适用于大多数情况。” - 在我看来,这使得使用正则表达式不好。给出误报或误报的正则表达式已损坏。
      【解决方案6】:

      如果您正在验证的数据的模式可以使用正则表达式完整且正确地表达,那么您可以放心地使用它们。然而,并非所有文本模式都可以使用正则表达式(例如上下文无关文法)来表达。在这种情况下,您可能需要编写解析器或自定义方法来验证数据。

      【讨论】:

        【解决方案7】:

        担心可能是因为使用的正则表达式通常覆盖所有可能的(有效)输入和/或限制用户在他可以输入什么。

        我认为没有其他方法可以验证某些用户输入是否与某个模式匹配(我的意思是,这就是正则表达式的用途),因此它们对于用户输入验证是必不可少的 (imo)。但是你肯定需要花一些时间来设计一个表达式,以确保它确实有效,在极端情况下也是如此。

        获取信用卡号码。您必须考虑用户可能输入它们的方式:

        1234-5678
        // or
        1234 5678
        // or
        1234 - 5678
        

        现在你有两种可能:

        1. 您将输入限制为第一种情况,这将导致更简单的表达,但会最大程度地限制(并且可能会惹恼)用户。
        2. 您创建的表达式接受任何这些可能性,使表达式更复杂(因此更难维护)但更易于使用。

        这是一种权衡。

        【讨论】:

        • 3.您接受任何输入但删除任何非数字字符,验证该值并根据需要重新格式化。
        • “担心可能是因为使用的正则表达式通常不能涵盖所有可能的(有效)输入和/或限制用户输入的内容。”这可以说是任何验证方法
        • @Gumbo:好点 :) 这在这里可能有用,但我更多地将其视为一般示例。
        【解决方案8】:

        如果是正则语言,正则表达式对于验证大多数数据来说都不错。

        但是,如前所述,有时它们会变得难以维护,并且程序员会引入错误。

        缓解这种情况的最简单方法是使用测试/TDD。这些测试应该调用一个使用正则表达式来验证电子邮件地址的方法(我目前使用这个正则表达式/^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$/i,它工作得很好。这样,当你得到一个误报或误报时,你可以添加另一个测试在这种情况下,请调整您的正则表达式,并确保您没有破坏其他条件。

        如果 TDD 看起来有点多,像 Expresso 这样的工具可以让您将正则表达式与测试数据一起保存,这有助于跟踪应该通过/失败的值,并有助于创建和理解您的正则表达式。

        警告:

        在构造正则表达式时要小心。有可能引入 ReDos 漏洞

        见:http://msdn.microsoft.com/en-us/magazine/ff646973.aspx

        简而言之,如果输入正确,构造不佳的正则表达式可能需要数小时才能有效地执行,从而降低服务器性能。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-06
          • 1970-01-01
          • 2011-03-04
          • 1970-01-01
          相关资源
          最近更新 更多