【问题标题】:Regex - Cost of an Item正则表达式 - 项目成本
【发布时间】:2010-11-12 16:23:27
【问题描述】:

正确提供了检查成本的正则表达式是什么:

  • 数字必须大于等于 0.01
  • 数字必须小于或等于 99.99

可能的匹配项是:

9 | 23.3 | 25.69

不允许:

  1. | 2.

【问题讨论】:

  • 这正是你不能用正则表达式做的事情。
  • .011. 应该有效吗?
  • 我认为用正则表达式来做这件事是不可行的。正则表达式是一种文本处理语言,您要求的是值的处理。不过,如果有人不这么认为,我很想听听。
  • @CodingG 你可以这样做。它是一组有限的有效值,所以它确实是可能的。
  • @lasseespeholt 任何事情都是可行的,但这并不意味着你应该去做。他没有提到任何语言或环境,但我必须相信他使用的任何东西都有更好的方法。

标签: ruby-on-rails regex


【解决方案1】:

当然,正确的方法是获取提供的字符串,将其转换为数字(如果它不是可解析的数字,则捕获错误),然后将其与有效值进行比较。

如果它必须是一个正则表达式,那当然是可能的,但很丑:

^(?:[1-9][0-9]?(?:\.[0-9]{1,2})?|0?.0[1-9]|0?.[1-9][0-9]?)$

说明:

^                   # start of string
(?:                 # either match
 [1-9][0-9]?        # a number between 1 and 99
 (?:\.[0-9]{1,2})?  # optionally followed by a decimal point and up to two digits
|                   # or
 0?.0[1-9]          # a number between 0.01 and 0.09 (optionally without leading 0)
|                   # or
 0?.[1-9][0-9]?     # a number between 0.1 and 0.99
)                   # end of alternation
$                   # end of string

当然,在大多数正则表达式方言中,您可以使用 \d 代替 [0-9] 而不会改变含义,但我认为在这种情况下,坚持使用较长的版本有助于提高可读性。

在 Ruby 中,假设您的输入字符串从不包含换行符:

if subject =~ /^(?:[1-9][0-9]?(?:\.[0-9]{1,2})?|0?.0[1-9]|0?.[1-9][0-9]?)$/
    # Successful match
else
    # Match attempt failed
end

由于您关心有效数字的数量,另一种解决方案是首先检查输入是否看起来像一个数字,如果它通过了该测试,则将其转换为浮点数并检查它是否在范围内。

^(\d{1,2}|\d{0,2}\.\d{1,2})$

将匹配 0 到 99.99 之间的任何数字(整数或小数点后两位数的小数)。然后你只需要检查数字是否> = 0.01。这种方法的优点是,如果对有效数字的要求发生变化,您可以轻松扩展小数点前后允许的数字范围,然后相应地调整值检查。

【讨论】:

  • 正则表达式效果很好,非常感谢。我在 RoR 中这样做,你能告诉我你会怎么做吗?
  • 如@Zano 所建议的那样,定期检查是最好的方法吗?
  • 这似乎是更自然的事情,特别是如果您的要求发生变化 - 想象一下明天您需要验证 0.07 到 218.39 之间的数字。
  • 我似乎无法使用浮点数进行迭代,(0.01..99.99) === 2.2222 返回 true,我希望它返回 false,有什么想法吗?
  • 2.2222 介于 0.01 和 99.99 之间,所以它当然返回 True。我会修改我的答案。
【解决方案2】:

我不确定您是否需要使用正则表达式来执行此操作,为什么不将字符串拆分为 '|'放入一个数组并检查数组中的每个元素是否大于 0.01 且小于 99.99

【讨论】:

    【解决方案3】:

    使用正则表达式的解决方案很难维护,因为它是一种非常奇怪且不直观的解决问题的方法。任何阅读您的代码的人(包括几周后的您自己)都很难理解检查的目的是什么。

    也就是说,假设值 0.00 - 99.99 是有效的,正则表达式可能是

    ^\d{0,2}(\.\d\d?)?$
    

    假设为 0.01 - 99.99,则稍微复杂一点:

    ^0{0,2}(\.(0[1-9]|[1-9]\d?))?|\d{0,2}(\.\d\d)?$
    

    别让我从 0.02 - 99.98 开始... :-)

    所以基本上,不要这样做。将字符串转换为数值,然后定期进行间隔检查。

    【讨论】:

    • 如何进行定期检查?
    • 类似if (0.01..99.99) === inputValueif (0.01..99.99).include?(inputValue)
    【解决方案4】:

    试试

    ^\d{1,2}(\.\d{1,2})?$  
    

    它检查是否有 1 位或 2 位数字,如果有一个点,它会检​​查点后是否有 1 位或 2 位数字。

    作为对您问题的 cmets 的回答:在将请求发送到服务器或其他东西之前,没有什么可以反对检查格式。范围检查可以在其他地方进行。

    【讨论】:

    • 但正如他在问题中所说,这不是格式检查,而是范围检查。
    【解决方案5】:

    这不是最好的,但很有效

    (0\.01|0\.02|0\.03| ... |99\.98|99\.99)
    

    【讨论】:

      【解决方案6】:

      由于您使用的是 Rails,因此在您的模型中使用 validates_numericality_of 可能会更好:

      validates_numericality_of :cost, :greater_than_or_equal_to => 0.01, 
                                       :less_than_or_equal_to => 0.99
      

      为防止出现小数便士,请将其与 validates_format_of 结合使用:

      validates_format_of :cost, :with => /\A\d*(\.\d{1,2})?\Z/
      

      这利用了每个验证的强度。

      【讨论】:

      • 这将允许例如 1.2333。
      猜你喜欢
      • 2014-06-08
      • 1970-01-01
      • 2023-03-24
      • 2017-01-27
      • 2014-04-24
      • 2010-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多