2012-12-12 85 views
2

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

正则表达式应该验证以下...

  • 美元符号可选
  • 负数以括号,而不是一个减号
  • 如果负所指,美元符号应在括号外
  • 逗号为可选
  • 最大数量为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})?))\)))$ 

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

+2

1:这可能在[codereview.se]属于。 2:正则表达式的语言是什么? 3:你考虑过哪些国际考虑? 4:'1.000,00','3.000' – zzzzBov

+0

你似乎没有多少括号。你是否需要所有人进行匹配组? – Bergi

+0

可能重复[什么是“最好”美国货币RegEx?](http://stackoverflow.com/questions/354044/what-is-the-best-us-currency-regex) –

回答

3

你可以表达“一个六位数之间;后三位前逗号是可选的”多一点简洁为\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?)?\))$ 

编辑补充:使用前向断言像FJ表明在他/她的回答,后者可以缩短为:

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

我忘了前导零。但是你的第二个正则表达式示例在测试时似乎不运行,是否缺少括号或什么? – gfrobenius

+0

当它,我的规格是错误的,如果使用美元符号,它必须在括号内。 – gfrobenius

+0

@gfrobenius:Re:第二个例子:它在Perl中工作。我敢打赌,ColdFusion不喜欢'\ d {,2}'符号;我将把它改为'\ d {0,2}'。 Re:圆括号内的美元符号:没问题,我也会解决的。 – ruakh

3

鉴于你的例子,下面的正则表达式将工作:

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

(注:标志和分隔符是语言相关)

此正则表达式设置了不必要的反向引用仅仅是为了保存正则表达式长度。你可以忽略第二个反向引用。如果这是不能容忍的话,表达会变得相当长。

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

+0

请注意, IF构造在正则表达式中并不常见。 – nhahtdh

9

这里是一个较短的替代(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 
+0

+1;这是一个很好的使用前瞻! – ruakh