7.4. 使用 {n,m} 语法

前面的章节,你处理了相同字符可以重复三次的情况。在正则表达式中,有另外一个方式来表达这种情况,并且能提高代码的可读性。首先看看我们在前面的例子中使用的方法。

例 7.5. 老方法:每一个字符都是可选的

>>> import re
>>> pattern = '^M?M?M?$'
>>> re.search(pattern, 'M')    
<_sre.SRE_Match object at 0x008EE090>
>>> pattern = '^M?M?M?$'
>>> re.search(pattern, 'MM')   
<_sre.SRE_Match object at 0x008EEB48>
>>> pattern = '^M?M?M?$'
>>> re.search(pattern, 'MMM')  
<_sre.SRE_Match object at 0x008EE090>
>>> re.search(pattern, 'MMMM') 
>>> 
这个模式匹配串的开始,接着是第一个可选的字符 M,第二第三个 M 字符则被忽略 (这是可行的,因为它们都是可选的),最后是字符串的结尾。
这个模式匹配串的开始,接着是第一和第二个可选字符 M,而第三个 M 字符被忽略 (这是可行的,因为它们都是可选的),最后匹配字符串的结尾。
这个模式匹配字符串的开始,接着匹配所有的三个可选字符 M,最后匹配字符串的结尾。
这个模式匹配字符串的开始,接着匹配所有的三个可选字符 M,但是不能够匹配字符串的结尾 (因为还有一个未匹配的字符 M),因此不能够匹配而返回一个 None

例 7.6. 一个新的方法:从 nm

>>> pattern = '^M{0,3}$'       
>>> re.search(pattern, 'M')    
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MM')   
<_sre.SRE_Match object at 0x008EE090>
>>> re.search(pattern, 'MMM')  
<_sre.SRE_Match object at 0x008EEDA8>
>>> re.search(pattern, 'MMMM') 
>>> 
这个模式意思是说:“匹配字符串的开始,接着匹配 0 到 3 个 M 字符,然后匹配字符串的结尾。”这里的 0 和 3 可以改成其它任何数字;如果你想要匹配至少 1 次,至多 3 次字符 M,则可以写成 M{1,3}
这个模式匹配字符串的开始,时时彩计划软件公式:接着匹配三个可选 M 字符中的一个,最后是字符串的结尾。
这个模式匹配字符串的开始,接着匹配三个可选 M 字符中的两个,最后是字符串的结尾。
这个模式匹配字符串的开始,接着匹配三个可选 M 字符中的三个,最后是字符串的结尾。
这个模式匹配字符串的开始,接着匹配三个可选 M 字符中的三个,但是没有匹配上 字符串的结尾。正则表达式在字符串结尾之前最多只允许匹配三次 M 字符,但是实际上有四个 M 字符,因此模式没有匹配上这个字符串,返回一个 None
没有一个轻松的方法来确定两个正则表达式是否等价。你能采用的最好的办法就是列出很多的测试样例,确定这两个正则表达式对所有的相关输入都有相同的输出。在本书后面的章节,将更多地讨论如何编写测试样例。

7.4.1. 校验十位数和个位数

现在我们来扩展一下关于罗马数字的正则表达式,以匹配十位数和个位数,下面的例子展示十位数的校验方法。

例 7.7. 校验十位数

>>> pattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)$'
>>> re.search(pattern, 'MCMXL')    
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCML')     
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLX')    
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLXXX')  
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLXXXX') 
>>> 
这个模式匹配字符串的开始,接着是第一个可选字符 M,接着是 CM,接着 XL,接着是字符串的结尾。请记住,(A|B|C) 这个语法的含义是“精确匹配 A、B 或者 C 其中的一个”。此处匹配了 XL,因此不再匹配 XCL?X?X?X?,接着就匹配到字符串的结尾。MCML 表示罗马数字 1940
这个模式匹配字符串的开始,接着是第一个可选字符 M,接着是 CM,接着 L?X?X?X?。在模式 L?X?X?X? 中,它匹配 L 字符并且跳过所有可选的 X 字符,接着匹配字符串的结尾。MCML 表示罗马数字 1950
这个模式匹配字符串的开始,接着是第一个可选字符 M,接着是 CM,接着是可选的 L 字符和可选的第一个 X 字符,并且跳过第二第三个可选的 X 字符,接着是字符串的结尾。MCMLX 表示罗马数字 1960
这个模式匹配字符串的开始,接着是第一个可选字符 M,接着是 CM,接着是可选的 L 字符和所有的三个可选的 X 字符,接着匹配字符串的结尾。MCMLXXX 表示罗马数字 1980
这个模式匹配字符串的开始,接着是第一个可选字符M,接着是CM,接着是可选的 L字符和所有的三个可选的X字符,接着就未能匹配 字符串的结尾ie,因为还有一个未匹配的X 字符。所以整个模式匹配失败并返回一个 None. MCMLXXXX 不是一个有效的罗马数字。

对于个位数的正则表达式有类似的表达方式,我将省略细节,直接展示结果。

>>> pattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$'

用另一种 {n,m} 语法表达这个正则表达式会如何呢?这个例子展示新的语法。

例 7.8. 用 {n,m} 语法确认罗马数字

>>> pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'
>>> re.search(pattern, 'MDLV')             
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MMDCLXVI')         
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MMMDCCCLXXXVIII')  
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'I')                
<_sre.SRE_Match object at 0x008EEB48>
这个模式匹配字符串的开始,接着匹配三个可选的 M 字符的一个,接着匹配 D?C{0,3},此处,仅仅匹配可选的字符 D 和 0 个可选字符 C。继续向前匹配,匹配 L?X{0,3},此处,匹配可选的 L 字符和 0 个可选字符 X,接着匹配 V?I{0,3},此处,匹配可选的 V 和 0 个可选字符 I,最后匹配字符串的结尾。MDLV 表示罗马数字 1555
这个模式匹配字符串的开始,接着是三个可选的 M 字符的两个,接着匹配 D?C{0,3},此处为一个字符 D 和三个可选 C 字符中的一个,接着匹配 L?X{0,3},此处为一个 L 字符和三个可选 X 字符中的一个,接着匹配 V?I{0,3},此处为一个字符 V 和三个可选 I 字符中的一个,接着匹配字符串的结尾。MMDCLXVI 表示罗马数字 2666
这个模式匹配字符串的开始,接着是三个可选的 M 字符的所有字符,接着匹配 D?C{0,3},此处为一个字符 D 和三个可选 C 字符中所有字符,接着匹配 L?X{0,3},此处为一个 L 字符和三个可选 X 字符中所有字符,接着匹配 V?I{0,3},此处为一个字符 V 和三个可选 I 字符中所有字符,接着匹配字符串的结尾。MMMDCCCLXXXVIII 表示罗马数字3888,这个数字是不用扩展语法可以写出的最大的罗马数字。
仔细看哪!(我像一个魔术师一样,“看仔细喽,孩子们,我将要从我的帽子中拽出一只兔子来啦!”) 这个模式匹配字符串的开始,接着匹配 3 个可选 M 字符的 0 个,接着匹配 D?C{0,3},此处,跳过可选字符 D 并匹配三个可选 C 字符的 0 个,接着匹配 L?X{0,3},此处,跳过可选字符 L 并匹配三个可选 X 字符的 0 个,接着匹配 V?I{0,3},此处跳过可选字符 V 并匹配三个可选 I 字符的一个,最后匹配字符串的结尾。哇赛!

如果你在第一遍就跟上并理解了所讲的这些,那么你做的比我还要好。现在,你可以尝试着理解别人大规模程序里关键函数中的正则表达式了。或者想象着几个月后回头理解你自己的正则表达式。我曾经做过这样的事情,但是它并不是那么有趣。

在下一节里,你将会研究另外一种正则表达式语法,它可以使你的表达式具有更好的可维持性。

时时彩4星组选走势图 时时彩后一选号软件 360江西时时彩走势图 时时彩直选终极版下载 江西时时彩开奖号码视频
对赌协议 王者软件彩票 世爵娱乐平台下载 旧时时彩开奖走势图 时时彩大小判断
吉林时时彩技巧稳赚 启航全天时时彩计划 新疆时时彩网易彩票网 江西时时彩后二投注 重庆时时彩万能六码
时时彩平台teafly 时时彩后二80码 魔方时时计划软件app 腾龙时时彩官网 新时时彩怎么计算
优游分分彩网页版 青海省十一选五开奖结果 云南快乐10分开奖号码 北京时时彩开奖结果 山西十一选五开奖结果?sayui取消一个复选框?新疆福彩35选七走势图?3d走势图
香港六合彩151期 云南十一选五开奘结果 大乐透计算器 速娱乐 吉林快三免费预测号码
北京快乐8是不是官方的 网上玩百家 乐破解法 湖北11选5软件安卓 江苏11选5方法 北京pk拾 吧
体育彩票福建22选5结果 陕西体彩 河南快三一定牛走势图 重庆快乐10分数字走势图 七星彩论坛