正则表达式有强大并且标准化的方法来处理字符串查找、替换以及用复杂模式来解析文本。在python中,正则表达式模块是re.
案例1:街道地址
\ | 转义字符 |
\b | 在右边必须有一个分隔符,可以用来匹配单词边界 |
\d | 匹配数字0~9 |
\D | 匹配任意的非数字字符 |
r | 字符串中没有任何字符需要转义 |
^ | 匹配字符串的开头 |
$ | 匹配字符串的结尾 |
x|x | 只匹配符号两边的其中一个 |
x?x | 符号左右两边的字符是可选的 |
(x) | 这是一个组,会记忆匹配到的字符 |
x* | 匹配X零或多次 |
x+ | 匹配X一或多次 |
x{n,m} | 匹配x至少n次,不少于m次 |
>>> import re
>>> s = '100 NORTH MAIN ROAD'
>>> re.sub('ROAD$','RD.',s)
'100 NORTH MAIN RD.'
>>> s = '100 BROAD'
>>> re.sub('ROAD$','RD.',s) '匹配部分是尾部包含ROAD的,无论是否是其他单词的一部分'
'100 BRD.'
>>> re.sub('\bROAD$','RD.',s) '匹配尾部单个单词'
'100 BROAD'
>>> re.sub(r'\bROAD$','RD.',s) 'r防止转义传染,视为原始字符串'
'100 BROAD'
>>> s = '100 BROAD ROAD APT.3'
>>> re.sub(r'\bROAD\b','RD.',s) '匹配字符串中任何位置的单词ROAD'
'100 BROAD RD. APT.3'
案例二:罗马数字
罗马数字主要是七个数字的不同组合:Ⅰ= 1、Ⅴ = 5、Ⅹ = 10、L = 50、C = 100、D = 500、M = 1000.
怎么验证罗马数字呢?可以从千位、百位、十位、个位分别入手。
①怎么验证一个罗马数字是否是一个千位数呢?
根据罗马数字组成规则,同一个符号不能出现四次,只会是0~3次,所以千位的正则表达式很明显是'^M?M?M$'。
②怎么验证百位呢?
100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 |
C | CC | CCC | CD | D | DC | DCC | DCCC | CM |
从表格中可以看出主要组成方式是:0~3个C,CD,D接0~3个C,CM,所以验证百位的正则表达式是:'^CD|CM|D?C?C?C$'
③验证十位
10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 |
X | XX | XXX | XL | L | LX | LXX | LXXX | XC |
从表格中可以看出主要组成方式是:0~3个X,XL,L接0~3个X,XC,所以验证百位的正则表达式是:'^XL|XC|L?X?X?X$'
④验证个位
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Ⅰ | Ⅱ | Ⅲ | Ⅳ | Ⅴ | Ⅵ | Ⅶ | Ⅷ | Ⅸ |
从表格中可以看出主要组成方式是:0~3个Ⅰ,Ⅳ,Ⅴ接0~3个Ⅰ,Ⅸ,所以验证百位的正则表达式是:'^Ⅳ|Ⅸ|Ⅴ?Ⅰ?Ⅰ?Ⅰ$'
综上,我们可以写出验证罗马数字的正则表达式了:
'^M?M?M?(CD|CM|D?C?C?C)(XL|XC|L?X?X?X)(Ⅳ|Ⅸ|Ⅴ?Ⅰ?Ⅰ?Ⅰ)$'
还有另一种更可读的表达方式:使用语法{n,m}
'^M{0,3}(CD|CM|D?C{0,3})(XL|XC|L?X{0,3})(Ⅳ|Ⅸ|Ⅴ?Ⅰ{0,3})$'
好了,正则表达式分析好了,来试试吧
>>> pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IV|IX|V?I{0,3})$'
>>> re.search(pattern, 'MMMDCCCLXXXVIII')
<re.Match object; span=(0, 15), match='MMMDCCCLXXXVIII'>
大功告成
为了让正则表达式可读性更好,我们还可以使用松散正则表达式,在松散表达式中可以加入一些。说明性语句,松散正则表达式与普通正则表达式有以下不同:
①空白符被忽略。空格、制表符和回车在正则表达式中并不会匹配空格、制表符、回车。如果你想在正则表达式中匹配他们,可以在前面加一个\来转义。
②注释信息被忽略。松散正字表达式中的注释和 python 代码中的一样,都是以#开头直到行尾。它可以在多行正则表达式中增加注释信息,这就避免了在 python 代码中的多行注释。他们的工作方式是一样的。
例子如下:
>>> pattern = '''^ # beginning of stringM{0,3} # thousands - 0 to 3 Ms(CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 Cs),# or 500-800 (D, followed by 0 to 3 Cs)(XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 Xs),# or 50-80 (L, followed by 0 to 3 Xs)(IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 Is),# or 5-8 (V, followed by 0 to 3 Is)$ # end of string'''
>>> re.search(pattern, 'M', re.VERBOSE)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLXXXIX', re.VERBOSE)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MMMDCCCLXXXVIII', re.VERBOSE)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'M')
注意,如果要使用松散正则表达式,需要传递一个叫re.VERBOSE 的参数,否则就会当作普通正则表达式来处理。
案例三:解析电话号码
Here are the phone numbers I needed to be able to accept:
800-555-1212
800 555 1212
800.555.1212
(800) 555-1212
1-800-555-1212
800-555-1212-1234
800-555-1212x1234
800-555-1212 ext. 1234
work 1-(800) 555.1212 #1234
Quite a variety! In each of these cases, I need to know that the area code was 800
, the trunk was 555
, and the rest of the phone number was 1212
. For those with an extension, I need to know that the extension was 1234
.
>>> phonePattern = re.compile(r'''# don't match beginning of string, number can start anywhere(\d{3}) # area code is 3 digits (e.g. '800')\D* # optional separator is any number of non-digits(\d{3}) # trunk is 3 digits (e.g. '555')\D* # optional separator(\d{4}) # rest of number is 4 digits (e.g. '1212')\D* # optional separator(\d*) # extension is optional and can be any number of digits$ # end of string''', re.VERBOSE)
>>> phonePattern.search('work 1-(800) 555.1212 #1234').groups()
('800', '555', '1212', '1234')
>>> phonePattern.search('800-555-1212')
('800', '555', '1212', '')
这一章正则表达式的学习就到这里了,有看到这里的人,希望对您有帮助。