使用正则表达式在JavaScript中验证货币金额。

6

可能重复:
有一个C#正则表达式可以验证货币、浮点数或整数吗?

如何使用JavaScript正则表达式验证货币金额?

小数分隔符: ,

十位、百位等分隔符: .

模式: ###.###.###,##

有效金额的示例:

1
1234
123456

1.234
123.456
1.234.567

1,23
12345,67
1234567,89

1.234,56
123.456,78
1.234.567,89

编辑

我忘记提到以下格式也是有效的:###,###,###.##


"12345"和"12345.67"也是有效的吗? - Hyperboreus
哦,我的天啊... 它也需要验证 印度格式 吗? :D - Denis de Bernardy
1
http://stackoverflow.com/search?q=javascript+currency+validation 对您没有帮助吗? - Felix Kling
3个回答

17

根据您提供的标准,这是我得出的结果。

/(?:^\d{1,3}(?:\.?\d{3})*(?:,\d{2})?$)|(?:^\d{1,3}(?:,?\d{3})*(?:\.\d{2})?$)/

演示

这很丑陋,而且随着您发现需要匹配的更多情况,它只会变得更糟。最好找到并使用一些验证库,而不是尝试自己完成所有操作,特别是不要在单个正则表达式中完成。

更新以反映添加的要求。


根据下面的评论再次更新。

它将匹配 123.123,123(三个尾随数字而不是两个),因为它接受逗号或点作为千位分隔符和小数点。为了修复这个问题,我现在基本上将表达式加倍;要么它使用逗号作为分隔符和点作为基数点来匹配整个内容,要么它使用点作为分隔符和逗号作为基数点来匹配整个内容。

明白我说的越来越乱了吗?(^_^)


这是一个详细的解释:
(?:^           # beginning of string
  \d{1,3}      # one, two, or three digits
  (?:
    \.?        # optional separating period
    \d{3}      # followed by exactly three digits
  )*           # repeat this subpattern (.###) any number of times (including none at all)
  (?:,\d{2})?  # optionally followed by a decimal comma and exactly two digits
$)             # End of string.
|              # ...or...
(?:^           # beginning of string
  \d{1,3}      # one, two, or three digits
  (?:
    ,?         # optional separating comma
    \d{3}      # followed by exactly three digits
  )*           # repeat this subpattern (,###) any number of times (including none at all)
  (?:\.\d{2})? # optionally followed by a decimal perioda and exactly two digits
$)             # End of string.

有一件事情让它看起来更加复杂,那就是其中所有的?:。通常正则表达式会捕获(返回匹配项)所有的子模式。而?:的作用只是告诉它不要去捕获这个子模式。所以从技术上讲,如果你把所有的?:都去掉,整个表达式仍然可以匹配你的整个字符串,这样看起来更清晰:

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

此外,正则表达式.info 是一个很好的资源。

在我接受你的答案之前,你能否更新正则表达式,使其不接受超过两位小数?例如:123.456,789。 - Diogo Cardoso
@Diogo 好的,看到我的更新了。 - Wiseguy
请问您能否更新以下冗长的正则表达式:http://pastebin.com/2heBURP7 - Diogo Cardoso
@Diogo 像这样吗?http://pastebin.com/at8hhuUt 其中一件使它看起来更复杂的事情是其中所有的 ?:。通常,正则表达式也会捕获(返回匹配项)所有子模式。所有 ?: 所做的就是说不要费力去捕获子模式。因此,从技术上讲,如果您将它们全部删除,它仍将匹配您的整个字符串,这看起来更清晰:/(^\d{1,3}(\.?\d{3})*(,\d{2})?$)|(^\d{1,3}(,?\d{3})*(\.\d{2})?$)/ - Wiseguy

8
这适用于您所有的示例:
/^(?:\d+(?:,\d{3})*(?:\.\d{2})?|\d+(?:\.\d{3})*(?:,\d{2})?)$/

作为详细的正则表达式(虽然 JavaScript 不支持):
^              # Start of string
(?:            # Match either...
 \d+           # one or more digits
 (?:,\d{3})*   # optionally followed by comma-separated threes of digits
 (?:\.\d{2})?  # optionally followed by a decimal point and exactly two digits
|              # ...or...
 \d+           # one or more digits
 (?:\.\d{3})*  # optionally followed by point-separated threes of digits
 (?:,\d{2})?   # optionally followed by a decimal comma and exactly two digits
)              # End of alternation
$              # End of string.

4
如果解释正则表达式的每个部分,就可以让人更容易理解,否则它们可能会让人眼睛疼痛。+1 - codingbadger
+1 同意Barry的观点。感谢您添加这个。在需求和我的答案最终确定之后,我也打算这样做,但是你比我更快。 - Wiseguy

0

这处理了除(刚添加的?)123.45 案例之外的所有内容:

function foo (s) { return s.match(/^\d{1,3}(?:\.?\d{3})*(?:,\d\d)?$/) }

你需要处理多种分隔符格式吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接