当前位置: 代码迷 >> 综合 >> 《Dive into python3》:Chapter5 Regular expressions(正则表达式)
  详细解决方案

《Dive into python3》:Chapter5 Regular expressions(正则表达式)

热度:25   发布时间:2023-12-23 10:57:41.0

正则表达式有强大并且标准化的方法来处理字符串查找、替换以及用复杂模式来解析文本。在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', '')

这一章正则表达式的学习就到这里了,有看到这里的人,希望对您有帮助。