Java正则表达式匹配美元金额

6

这是我一直在使用的东西。

\$?[0-9]+\.*[0-9]*

但是在进行一些测试时,我注意到像这样的事情:
$$$34.00 

如果用户输入超过一个美元符号,我不想让它甚至通过正则表达式,尽管 matcher.group() 返回匹配的子字符串,但会返回一个匹配项。因此我尝试了以下方法:

\${1}[0-9]+\.*[0-9]*

但是这似乎与我最初输入的正则表达式行为相同。现在我正在Java中进行测试,但我计划使用Boost库在C ++中使用它。但是请不要在这里给我那个解决方案,因为我想学习而不是让别人给我答案。

但是我确实需要帮助,使用户只能输入一个美元符号(这就是我认为\${1}会做的事情)


它是否也允许一堆连续的句点? - Dave Newton
你可以像这样指定字符串的开头和结尾:^${1}[0-9]+.[0-9]$ - Eric K Yung
整个字符串的数量是多少?另外,你目前是如何匹配它的?使用 .find() 吗? - fge
是的,我正在使用 matcher.find() - rage
@Eric.K.Yung 看起来 ^$?[0-9]+.[0-9]$ 可以满足我的需求。我希望用户可以输入带或不带美元符号的金额。 - rage
我知道这是一个老问题,但这个网站确实帮助我理解了正则表达式 https://regexr.com - brandito
6个回答

19
我建议在解析货币时避免使用正则表达式,尤其是当Java提供了更简单的解决方案时。请考虑以下代码:
String str = "$789.11"; // user entered value
Number number = null;
try {
    number = NumberFormat.getCurrencyInstance(Locale.US).parse(str);
} catch(ParseException pe) {
    // ignore
}

if (number != null) {
   // proceed as user entered a good value
}
else {
   // user didn't enter a good value
}

2
真遗憾我不能给这个点赞更多次。 - sjr
1
这很不错,我一定会把它存储在我的工具箱中,但是我正在尝试学习正则表达式,所以我正在寻找解决此问题的方法。 - rage
是的,当然可以。但是请注意,货币字符串也可以包含逗号,例如 $23,456.78 - anubhava
@rage:查看此答案,获取有关使用正则表达式解析美元货币字符串的一些指针:https://dev59.com/BnRC5IYBdhLWcg3wRO3k - anubhava
2
.parse(str) 方法接受不正确的字符串,例如 $12asdf - Dean Schulze
我同意迪恩的观点。我认为主要回答不是+1。 - ozn

14

由于您正在使用正则表达式进行学习,因此:

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

分解如下:

^\$ 字符串起始位置为单个美元符号 $。

([1-9]\d{0,2}(,\d{3})*) 1-3位数字,第一位数字不是0,后跟0个或多个逗号和3个数字的组合。

或者

(([1-9]\d*)?\d) 1个或多个数字,如果它是唯一的数字,则第一个数字可以为0。

(\.\d\d)?$ 在字符串结尾处,可以选择性地包含句点和2位小数。

匹配结果:

$4,098.09
$4098.09
$0.35
$0
$380

不匹配:

$098.09
$0.9
$10,98.09
$10,980456

(([1-9]\d*)?\d) 还会处理用户没有输入逗号的情况,我很高兴你发了这个答案,因为我从分解这个正则表达式并逐个理解它中学到了很多。 - rage
是的,这部分专门用于捕获字符串中未使用逗号的情况。 - Syon
什么是使$amount单独的相反操作? - Ashok kumar Ganesan

2
您可以在开头使用类似于[^\$]*\$?的内容。这样可以确保没有重复的$符号,但是也会匹配如果没有$符号出现的情况。
此外,如果您正在处理货币(可能有小数点和2位小数),您应该使用[\.\d{2}]?. 这意味着如果它后面跟着一个句点和两个数字或什么都没有,它就可以匹配成功。正如评论中所述,它也可以匹配多个连续的句点,因此您不应该在\.之后使用*量词。

我不想强制用户添加他不需要的分数。\.{0,1} 可以解决这个问题吗? - rage
\.?\.{0,1} 相同。? 量词表示它要么发生一次,要么不发生。您还应该在小数点后包括两个可能的分位数字,就像我在我的答案中展示的一样。如果没有它们,$27.50 将只匹配 $27. - Song Gao

1
您缺少字符串的开头符号^和结尾符号$
^\$\d+([.][0-9]+)?$

0

我知道这有点晚了,但这对我来说似乎有效

(\$)?[0-9]+\.*[0-9]*

我不明白为什么它对你不起作用。

0

[$](([1-9]+\.?\d*)|([0]\.\d*)|[0]) 正则表达式在这种情况下非常理想。

这是标准的 Perl 正则表达式,但可以在一些库中用于 JAVA。


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