【问题标题】:Currency Regular Expression货币正则表达式
【发布时间】:2012-11-30 16:15:15
【问题描述】:

我想我为我需要的东西创建了一个有效的正则表达式。只是想知道是否有人可以打破它或看到更短的编写方法。

正则表达式应验证以下内容...

  • 美元符号可选
  • 用括号表示负数,而不是减号
  • 如果为负数,美元符号应在括号外
  • 逗号是可选的
  • 最大数量为 999999.99
  • 最小值为 (999999.99)
  • 不必提供小数,但如果提供,不超过两个 数字

所以这里有一些有效的例子......

9
$9
$0.99
($999,999.99)
(999999)
($999999)
(999,999)
99,999.9

这是我想出的:

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

更正,我的规范是错误的,如果使用美元符号,它必须在括号内。

【问题讨论】:

  • 1:这可能属于Code Review。 2:正则表达式是什么语言? 3:您对 i18n 有哪些考虑? 4:1.000,003.000
  • 你似乎有很多不必要的括号。您需要所有这些来匹配组吗?

标签: regex


【解决方案1】:

你可以用\d{1,3}(,?\d{3})? 更简洁地表达“一位到六位数字之间;最后三位数字之前的逗号是可选的”。这也允许您只包含两个 (\.\d{1,2})? 副本:一份用于正面,一份用于负面,而不是一份用于无逗号的正数,一份用于带逗号的正数,等等。

另外,\d{1,2} 可以稍微缩短为 \d\d?,但我不确定这是否是一种改进。

所以,除非使用像 (?(1)) 这样的符号来测试是否设置了反向引用,这是我看到的最短版本:

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

您的正则表达式和这个正则表达式的一个可能不受欢迎的方面是它们将允许$00,012.7 之类的东西,即使没有人以这种方式使用前导零。您可以通过要求第一个数字为非零,然后添加一个特殊情况来处理 $0(0.12) 等来解决这个问题:

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

编辑添加:使用 F.J 在他/她的回答中建议的前瞻断言,后者可以缩短为:

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

【讨论】:

  • 我忘记了前导零。但是您的第二个正则表达式示例在测试时似乎没有运行,是缺少括号还是什么?
  • 该死,我的规范是错误的,如果使用美元符号,它必须在括号内。
  • @gfrobenius:回复:第二个示例:它适用于 Perl。我打赌 ColdFusion 不喜欢 \d{,2} 符号;我将其更改为\d{0,2}。回复:括号内的美元符号:没问题,我也会解决这个问题。
【解决方案2】:

这是一个较短的替代方案(56 个字符到 114 个字符),它适用于几乎所有正则表达式风格:

^\$?(?=\(.*\)|[^()]*$)\(?\d{1,3}(,?\d{3})?(\.\d\d?)?\)?$

示例:http://www.rubular.com/r/qtYHEVzVK7

解释:

^                # start of string anchor
\$?              # optional '$'
(?=              # only match if inner regex can match (lookahead)
   \(.*\)          # both '(' and ')' are present
   |               # OR
   [^()]*$         # niether '(' or ')' are present
)                # end of lookaheand
\(?              # optional '('
\d{1,3}          # match 1 to 3 digits
(,?\d{3})?       # optionally match another 3 digits, preceeded by an optional ','
(\.\d\d?)?       # optionally match '.' followed by 1 or 2 digits
\)?              # optional ')'
$                # end of string anchor

【讨论】:

    【解决方案3】:

    根据您的示例,以下正则表达式将起作用:

    /^(\$?(?(?=\()(\())\d+(?:,\d+)?(?:\.\d+)?(?(2)\)))$/gm
    

    (注意:标志和分隔符取决于语言)

    这个正则表达式设置一个不必要的反向引用仅仅是为了节省正则表达式的长度。您可以忽略第二个反向引用。如果这是无法容忍的,那么表达式会变得相当长。

    看看这里:http://regex101.com/r/fH3lV1

    【讨论】:

    • 请注意,IF 结构在正则表达式中并不常见。
    猜你喜欢
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-26
    相关资源
    最近更新 更多