问题描述
我想我为我需要的东西创建了一个有效的正则表达式.只是想知道是否有人可以打破它或看到更短的编写方式.
正则表达式应验证以下内容...
- 美元符号可选
- 负数用括号表示,而不是减号
- 如果为负数,美元符号应在括号外
- 逗号是可选的
- 最大数量为 999999.99
- 最小号码是 (999999.99)
- 不必提供小数,但如果提供,则不超过两个数字
这里有一些有效的例子......
99 美元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})?))\)))$
更正,我的规范是错误的,如果使用美元符号,它必须在括号内.
您可以将一位到六位数字之间;最后三位数字前的逗号是可选的"更简洁地表达为 \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?)?\)?$
I think I created a working regular expression for what I need. Just wondering if anyone can break it or see a shorter way to write it.
The regular expression should validate the following...
- Dollar sign optional
- Negative numbers signified with parenthesis, not a minus
- If negative, dollar sign should be outside the parenthesis
- Commas are optional
- Max number is 999999.99
- Min number is (999999.99)
- Decimals do not have to be supplied, but if so, no more than twodigits
So here are some examples of valid ones...
9
$9
$0.99
($999,999.99)
(999999)
($999999)
(999,999)
99,999.9
This is what I have come up with:
^\$?(((\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})?))\)))$
CORRECTION, my spec was wrong, if the dollar sign is used it must be INSIDE the parenthesis.
You can express "between one and six digits; comma before the last three digits is optional" a bit more tersely as \d{1,3}(,?\d{3})?
. This also allows you to include only two copies of (\.\d{1,2})?
: one for positive and one for negative, instead of one for positive-without-comma, one for positive-with-comma, etc.
Also, \d{1,2}
can be shortened slightly to \d\d?
, though I'm not sure if that's an improvement.
So, barring some notation like (?(1))
to test if a backreference is set, here's the shortest version I see:
^(\$?\d{1,3}(,?\d{3})?(\.\d\d?)?|\(\$?\d{1,3}(,?\d{3})?(\.\d\d?)?\))$
One perhaps-undesirable aspect of your regex, and of this one, is that they will allow something like $00,012.7
, even though no one uses leading zeroes that way. You can address that by requiring the first digit to be nonzero, and then adding a special case to handle $0
and (0.12)
and so on:
^(\$?(0|[1-9]\d{0,2}(,?\d{3})?)(\.\d\d?)?|\(\$?(0|[1-9]\d{0,2}(,?\d{3})?)(\.\d\d?)?\))$
Edited to add: using a lookahead assertion like F.J suggests in his/her answer, the latter can be shortened to:
^(?!\(.*[^)]$|[^(].*\)$)\(?\$?(0|[1-9]\d{0,2}(,?\d{3})?)(\.\d\d?)?\)?$
这篇关于货币正则表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!