什么是“最好的”美国货币 RegEx?

Posted

技术标签:

【中文标题】什么是“最好的”美国货币 RegEx?【英文标题】:What is "The Best" U.S. Currency RegEx? 【发布时间】:2010-09-26 03:00:32 【问题描述】:

快速搜索货币正则表达式会弹出a lot of results。

我在选择一个时遇到的问题是,如果不测试所有边缘情况,就很难验证正则表达式。是否有人拥有经过彻底测试的美元正则表达式?

我唯一的要求是匹配的字符串是美国货币并解析为System.Decimal

[ws][sign][digits,]digits[.fractional-digits][ws] 方括号([ 和 ])中的元素是可选的。 下表描述了每个元素。 元素描述 ws 可选的空格。 标志 可选标志。 数字 范围从 0 到 9 的数字序列。 , 特定于文化的千位分隔符。 .特定于文化的小数点符号。 小数位数 范围从 0 到 9 的数字序列。

【问题讨论】:

我会再添加一个潜在问题 - 使用括号代替符号。这是会计中相当普遍的惯例。 您引用的MSDN 允许00000000042。呜呜。 【参考方案1】:

这里有一些来自 Regex Buddy 制造商的东西。这些来自图书馆,所以我相信它们已经过彻底的测试。

数字:货币金额(必须为美分) 可选的千位分隔符;强制两位小数

Match; JGsoft:
^[+-]?[0-9]1,3(?:,?[0-9]3)*\.[0-9]2$

数字:货币金额(美分可选) 可选的千位分隔符;可选的两位小数

Match; JGsoft:
^[+-]?[0-9]1,3(?:,?[0-9]3)*(?:\.[0-9]2)?$

数字:货币金额美国和欧盟(美分可选) 可以使用美式 123,456.78 表示法和欧式 123.456,78 表示法。可选的千位分隔符;可选的两位小数

Match; JGsoft:
^[+-]?[0-9]1,3(?:[0-9]*(?:[.,][0-9]2)?|(?:,[0-9]3)*(?:\.[0-9]2)?|(?:\.[0-9]3)*(?:,[0-9]2)?)$

【讨论】:

现在已经很老了,但是这个正则表达式不能很好地处理可选逗号。数字11111111,111,111111.11 显然格式不正确,但这个正则表达式会匹配它。 @Keng,我同意它满足 OP 的需求,只是做笔记,因为这是一个名为 What is “The Best” U.S. Currency RegEx 的问题的答案 我认为我们可以通过将 (?:,?[0-9]3)* 替换为 (?:(,[0-9]3)*|([0-9]3)*) 来解决可选逗号问题。逗号无处不在或没有逗号。 这个答案将通过正则表达式上方的示例数字来改进,而不是(或以及)单词描述。 @Keng 现在是 2020 年,我仍然在乎 - 正则表达式不会像牛奶一样过期。【参考方案2】:

我在 www.RegExLib.com 的 Kirk Fuller, Gregg Durishan 上在线找到了这个正则表达式

过去几年我一直在成功使用它。

"^\$?\-?([1-9]1[0-9]0,2(\,\d3)*(\.\d0,2)?|[1-9]1\d0,(\.\d0,2)?|0(\.\d0,2)?|(\.\d1,2))$|^\-?\$?([1-9]1\d0,2(\,\d3)*(\.\d0,2)?|[1-9]1\d0,(\.\d0,2)?|0(\.\d0,2)?|(\.\d1,2))$|^\(\$?([1-9]1\d0,2(\,\d3)*(\.\d0,2)?|[1-9]1\d0,(\.\d0,2)?|0(\.\d0,2)?|(\.\d1,2))\)$"

【讨论】:

虽然我的测试不是权威的,但这个对我有用。接受:123 123.00 $123.00 1234 $1234 $1234.00 $1,234.00 拒绝:#123 1,2,34 我发现唯一的问题是它接受了 123.4 工作,工作的人想要 123.4 作为有效的美元金额。 就是这样 如何在 javascript 中运行它? 就我而言,123.4 很好 - 如果人们不知道如何正确从 Excel 导出,他们可能会导出 123.4 而不是 0.40,而且我发现 Tabula 有时会漏掉某些导入的最后一位数字。就是这样。【参考方案3】:

根本没有经过彻底测试(我只是写了它!),但似乎表现正确:

^-?(?:0|[1-9]\d0,2(?:,?\d3)*)(?:\.\d+)?$

测试集:

0
1
33
555
4,656
4656
99,785
125,944
7,994,169
7994169
0.00
1.0
33.78795
555.12
4,656.489
99,785.01
125,944.100
-7,994,169
-7994169.23 // Borderline...

Wrong:
000
01
3,3
5.
555,
,656
99,78,5
1,25,944
--7,994,169
0.0,0
.10
33.787,95
4.656.489
99.785,01
1-125,944.1
-7,994E169

注意:您的 System.Decimal 取决于语言环境,很难在正则表达式中制作,除非在构建它时。我假设数字按三分组,即使在某些文化(语言环境)中存在不同的规则。 在它周围添加空格是微不足道的。

【讨论】:

@RonRoyston 最初的问题要求数字出现在小数点之前...(请参阅错误测试集中的 .10 案例)。 0.75 确实通过了,当我转到 regex101.com 时,粘贴我的表达式并添加你的两个案例。【参考方案4】:

如果您想考虑人为错误,您可以在匹配货币时使正则表达式更加宽容。我使用了 Keng 的第二个不错的正则表达式,并使它更健壮地解决了拼写错误。

\$\ ?[+-]?[0-9]1,3(?:,?[0-9])*(?:\.[0-9]1,2)?

这将匹配任何这些正确或损坏的货币数字,但不会在空格后面拾取多余的垃圾:

$46,48382
$4,648,382
$ 4,648,382
$4,648,382.20
$4,648,382.2
$4,6483,82.20
$46,48382 70.25PD
$ 46,48382 70.25PD

【讨论】:

【参考方案5】:

Keng 的答案很完美,我只想补充一点,以使用 1 位或 2 位小数(第三版):

"^[+-]?[0-9]1,3(?:[0-9]*(?:[.,][0-9]1)?|(?:,[0-9]3)*(?:\.[0-9]1,2)?|(?:\.[0-9]3)*(?:,[0-9]1,2)?)$

网络提琴: https://dotnetfiddle.net/1mUpX2

【讨论】:

【参考方案6】:

这个问题已经有几年了,所以我想给出一个更新的答案。

我使用过jQuery InputMask,它在输入/格式屏蔽(例如电话号码等)方面效果很好,但根据我的经验,它对货币的效果并不好。

对于货币,我强烈推荐autoNumeric jQuery 插件。它维护得很好,他们基本上“想到了一切”我想要的货币。

我实际上结合使用这两个插件来格式化电话号码、数字格式(ISBN 等)以及货币(主要是美元)。

请记住,jquery.inputmask 主要是关于控制值的格式,而autoNumeric 是关于专门控制货币的格式。

【讨论】:

确实,仅尝试使用正则表达式只会让您感到痛苦和绝望。查看 AutoNumeric 代码行数(截至今天):~/dev/autoNumeric » cat src/*|wc -l -> 10851。这只是当今用于格式化货币的最完整的库,并且确实经过彻底测试 ;) (免责声明;我是它的维护者之一) 你能举个例子,使用这个库从字符串中提取货币值吗? @Ari:这些库更多的是在用户将数据输入到输入字段时控制数据的格式;我不使用它们从字符串中提取货币。要从字符串中提取货币,您可以使用正则表达式删除任何不是 0-9 和小数的内容,然后将其转换为浮点数,然后我建议将货币值作为美分存储在数据库中。未经测试的伪代码:"$123,456.78".gsub(/^[0-9]\./, "").to_f => 123456.78(请注意,这允许多个小数位,但要证明浓度)。【参考方案7】:

/^[-]?[$]\d1,3(?:,?\d3)*\.\d2$/ 是我想出的 - 我看到了类似的答案,但我只是使用了 \d 而不是 [0-9]

【讨论】:

这个截图出自哪里?【参考方案8】:

我正在使用以下正则表达式进行货币验证:

^-?0*(?:\d+(?!,)(?:\.\d1,2)?|(?:\d1,3(?:,\d3)*(?:\.\d1,2)?))$

您还可以允许可选的前导美元符号:

^\$?-?0*(?:\d+(?!,)(?:\.\d1,2)?|(?:\d1,3(?:,\d3)*(?:\.\d1,2)?))$

您可以通过添加轻松添加括号测试而不是符号

\( and \)

【讨论】:

【参考方案9】:

我也在研究这个问题,并得出结论,最好根据当前文化构建正则表达式。 我们可以使用

CurrencyPositivePattern 
CurrencyGroupSeparator
CurrencyDecimalSeparator

NumberFormatInfo 的属性以获取所需的格式。

编辑:像这样

NumberFormatInfo nfi = CultureInfo.CurrentCulture.NumberFormat;
      // Assign needed property values to variables.
      string currencySymbol = nfi.CurrencySymbol;
      bool symbolPrecedesIfPositive = nfi.CurrencyPositivePattern % 2 == 0;
      string groupSeparator = nfi.CurrencyGroupSeparator;
      string decimalSeparator = nfi.CurrencyDecimalSeparator;

      // Form regular expression pattern.
      string pattern = Regex.Escape( symbolPrecedesIfPositive ? currencySymbol : "") + 
                       @"\s*[-+]?" + "([0-9]0,3(" + groupSeparator + "[0-9]3)*(" + 
                       Regex.Escape(decimalSeparator) + "[0-9]+)?)" + 
                       (! symbolPrecedesIfPositive ? currencySymbol : ""); 

参考 - http://msdn.microsoft.com/en-us/library/hs600312.aspx

【讨论】:

@Robert-levy:添加参考 msdn.microsoft.com/en-us/library/hs600312.aspx 这可能会通过说它是用于 c# 来改进【参考方案10】:

我在这方面取得了成功(从上面的一些正则表达式中获取点点滴滴)。最多只能处理数千个,但扩展它应该不会太难

case class CurrencyValue(dollars:Int,cents:Int)
def cents = """[\.\,]""".r ~> """\d0,2""".r ^^ 
  _.toInt

def dollarAmount: Parser[Int] = """[1-9]1[0-9]0,2""".r ~ opt( """[\.\,]""".r ~> """\d3""".r) ^^ 
  case x ~ Some(y) => x.toInt * 1000 + y.toInt
  case x ~ None => x.toInt

def usCurrencyParser = """(\$\s*)?""".r ~> dollarAmount ~ opt(cents) <~ opt( """(?i)dollars?""".r) ^^ 
  case d ~ Some(change) => CurrencyValue(d, change)
  case d ~ None => CurrencyValue(d, 0)

【讨论】:

【参考方案11】:

这是我用的:

没有前导 + 或 -

^\$\d1,3\.[0-9]2$|^\$(\d1,3,)+\d3\.[0-9]2$

带有可选的前导 + 或 -

^[+-]?\$\d1,3\.[0-9]2$|^[+-]?\$(\d1,3,)+\d3\.[0-9]2$

网络小提琴: https://jsfiddle.net/compsult/9of63cwk/12/

【讨论】:

【参考方案12】:

使用 Leandro 的答案,我在开头添加了 ^(?:[$]|) 以允许前面的美元符号

^(?:[$]|)[+-]?[0-9]1,3(?:[0-9]*(?:[.,][0-9]1)?|(?:,[0-9]3)*(?:\.[0-9]1,2)?|(?:\.[0-9]3)*(?:,[0-9]1,2)?)$

这个匹配

136,402.99
25.27
0.33
$584.56
1
00.2
3,254,546.00
$3,254,546.00
00.01
-0.25
+0.85
+100,052.00

不匹配

11124.52
234223425.345
234.
.5234
a
a.23
32.a
a.a
z548,452.22
u66.36

【讨论】:

【参考方案13】:

这个呢?更短更优雅

(?:\,|\.?\d)*

【讨论】:

以上是关于什么是“最好的”美国货币 RegEx?的主要内容,如果未能解决你的问题,请参考以下文章

活动回顾 | 从《美国货币史》看,比特币是更好的货币吗?

记账货币

西部世界今日评论:Filecoin基金会主席出席美国参议院听证会“加密货币有什么好处”

美国考虑发 央行数字货币

客户端验证美国货币

美国考虑发 央行数字货币,