<p>假设您希望允许<code>$5.</code>,但不允许<code>5.</code>,则以下语言将被接受:</p>
<pre><code>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.
]))
</code></pre>
<p>需要理解的重要内容:</p>
<ul>
<li><code>^</code>和<code>$</code>分别只在输入字符串的开头和结尾匹配。</li>
<li><code>\.</code>匹配文本点</li>
<li><code>\$</code>匹配文本美元符号
<ul>
<li><code>\$?</code>匹配美元符号或不匹配(<em>即</em>,可选美元符号)</li>
</ul></li>
<li><code>\d</code>匹配任何单个数字(0-9)
<ul>
<li><code>\d*</code>匹配零个或多个数字的运行</li>
<li><code>\d+</code>匹配一个或多个数字的运行</li>
<li><code>\d{1,2}</code>匹配任何一个数字或两个数字的运行</li>
</ul></li>
</ul>
<p>带括号的子模式是捕获组:与捕获组中的子表达式匹配的输入中的所有文本都将在<code>matchobj.group(index)</code>中可用。美元符号不会被捕获,因为它在括号外。</p>
<p>因为Python不支持多个同名的捕获组(!!!)我们必须在<code>matchobj.groups()</code>中搜索不在<code>None</code>中的那个。这也意味着您在修改模式以对除数量之外的每个组使用<code>(?:...)</code>时必须小心。</p>
<p>调整马克的测试套,我们得到</p>
<pre><code>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
</code></pre>
<p>输出:</p>
<pre>
.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)</pre>