有人能解释一下只检查值是否匹配某个模式的金钱正则表达式吗?
这里有很多帖子讨论如何处理数值,但我只是想确认一下这个数值到底是什么。简单来说,我想弄清楚检查一个数值和“捕获”一个数值之间的区别。在这个情况下,数值指的是一些可以接受的货币格式:
这里有一篇帖子,里面解释了一些关于货币正则表达式的内容,但我一点也不明白。
.50
50
50.00
50.0
$5000.00
$.50
我不想要逗号(大家应该知道这很荒谬)。
我遇到的问题是:
- 允许在数值开头有一个$符号(但这个符号是可选的)
- 只允许有一个小数点(但不允许小数点在最后)
- 理解它是如何工作的
- 还想知道如何得到一个标准化的版本(只包含数字和可选的小数点),并去掉美元符号。
我现在的正则表达式(显然不太对)是:
# I'm checking the Boolean of the following:
re.compile(r'^[\$][\d\.]$').search(value)
(注意:我在使用Python)
4 个回答
4
还需要弄明白如何从中提取一个标准化的版本(只包含数字和可选的小数点),并去掉美元符号。
这也被称为“捕获”这个数值;)
基于Aaron的基本例子:
/^\$?(\d+(?:\.\d{1,2})?)$/
那么去掉美元符号后的金额会在捕获组1中。
8
这里有一个你可以使用的正则表达式:
regex = re.compile(r'^\$?(\d*(\d\.?|\.\d{1,2}))$')
这是我用来测试这个正则表达式的测试环境。我把你所有的测试都放进来了,还有我自己加的一些测试。我也加入了一些负面测试,因为确保它在不应该匹配的时候确实不匹配,和确保它在应该匹配的时候确实匹配一样重要。
tests = [
('.50', True),
('50', True),
('50.00', True),
('50.0', True),
('$5000', True),
('$.50', True),
('$5.', True),
('$5.000', False),
('5000$', False),
('$5.00$', False),
('$-5.00', False),
('$5,00', False),
('', False),
('$', False),
('.', False),
]
import re
regex = re.compile(r'^\$?(\d*(\d\.?|\.\d{1,2}))$')
for test, expected in tests:
result = regex.match(test)
is_match = result is not None
print test + '\t' + ('OK' if is_match == expected else 'Fail')
如果你想得到没有$符号的值,可以使用捕获组:
print result.group(1)
17
假设你想允许 $5.
这种格式,但不想允许 5.
,那么下面的内容可以帮助你理解如何设置你的规则:
money = re.compile('|'.join([
r'^\$?(\d*\.\d{1,2})$', # e.g., $.50, .50, $1.50, $.5, .5
r'^\$?(\d+)$', # e.g., $500, $5, 500, 5
r'^\$(\d+\.?)$', # e.g., $5.
]))
这里有几个重要的点需要明白:
^
和$
分别表示输入字符串的开始和结束。\.
表示一个字面上的点(小数点)。\$
表示一个字面上的美元符号。\$?
表示一个美元符号或者什么都没有(也就是说,美元符号是可选的)。
\d
表示任何一个数字(0-9)。\d*
表示零个或多个数字。\d+
表示一个或多个数字。\d{1,2}
表示一个数字或者两个数字。
括号中的子模式是捕获组:输入中与捕获组匹配的所有文本都可以通过 matchobj.group(index)
来获取。美元符号不会被捕获,因为它在括号外面。
因为 Python 不支持多个同名的捕获组(!!!),所以我们必须在 matchobj.groups()
中查找那个不是 None
的组。这也意味着在修改模式时,你需要小心,除了金额以外的每个组都要使用 (?:...)
。
调整 Mark 的测试工具后,我们得到了:
for test, expected in tests:
result = money.match(test)
is_match = result is not None
if is_match == expected:
status = 'OK'
if result:
amt = [x for x in result.groups() if x is not None].pop()
status += ' (%s)' % amt
else:
status = 'Fail'
print test + '\t' + status
输出结果:
.50 OK (.50) 50 OK (50) 50.00 OK (50.00) 50.0 OK (50.0) $5000 OK (5000) $.50 OK (.50) $5. OK (5.) 5. OK $5.000 OK 5000$ OK $5.00$ OK $-5.00 OK $5,00 OK OK $ OK . OK .5 OK (.5)