re模块(2)
正则表达式(RE)本质是一门小型,高度专业化的编程语言。只为匹配字符而存在
语法:
re.match(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
正则表达式修饰符 - 可选标志 flags
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
常用正则表达式符号
'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以 '*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a'] '+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb'] '?' 匹配前一个字符1次或0次 '{m}' 匹配前一个字符m次 '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb'] '|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC' '(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的 '\Z' 匹配字符结尾,同$ '\d' 匹配数字0-9 '\D' 匹配非数字 '\w' 匹配[A-Za-z0-9] '\W' 匹配非[A-Za-z0-9] 's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t' '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}
最常用的匹配语法
re.match 从头开始匹配 re.search 匹配包含 re.findall 把所有匹配到的字符放到以列表中的元素返回 re.splitall 以匹配到的字符当做列表分隔符 re.sub 匹配字符并替换
反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
仅需轻轻知道的几个匹配模式
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同) M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图) S(DOTALL): 点任意匹配模式,改变'.'的行为
练习:
1 #! usr/bin/env pyhton 2 # -*- coding:utf-8 -*- 3 import re 4 print("字符串提供的方法是完全匹配".center(50,'#')) 5 s='hello world' 6 7 print(s.find('llo')) 8 print(s.replace('ll','xx')) 9 print(s.split('o')) 10 11 print("正则表达式".center(50,'#')) 12 #re.findall(pattern=,string=,flags=) 13 #pattern 属性规定用于验证输入字段的模式。 模式指的是正则表达式。也可以理解成匹配规则 14 #string 匹配的内容 15 16 print('#示例:',re.findall('w\w{2}l',s)) 17 print('演示 . 通配符'.center(20,'*')) 18 print('#完全匹配:',re.findall('monday','dafdmondayafweryewrewmondaydsfwersfa')) 19 print('“.”默认匹配除\\n之外的任意一个字符',re.findall('w..l','hello world'))#'.'只能代指一个字符 20 print('使用.匹配换行符:',re.findall('w..l','hello wo\nld',re.S)) 21 22 print('演示 ^ 尖角符'.center(20,'*')) 23 print('^从开头匹配字符',re.findall('^m....y','mondayaf')) 24 print('^从开头匹配字符',re.findall('^m....y','mondaxaf')) 25 26 print('$从结尾匹配字符',re.findall('a..f$','mondayaf')) 27 print('$从结尾匹配字符',re.findall('a..f$','mondbxaf')) 28 print('$从结尾匹配字符',re.findall('a..f$','mondaxad')) 29 30 print('* 重复匹配:',re.findall('mon.*day','defadsemklmonuoidday')) 31 print('* 重复匹配:',re.findall('.*','defadsemklmonuoidday')) 32 print('* 重复匹配:',re.findall('ay*','defadsemklmonuoidday')) 33 print('* 重复匹配:',re.findall('y*','defadsemklmonuoidday')) 34 35 print('+匹配前一个字符1次或多次',re.findall('mon.+day','defadsemklmonuoidday')) 36 print('+匹配前一个字符1次或多次',re.findall('.+','defadsemklmonuoidday')) 37 print('+匹配前一个字符1次或多次',re.findall('ay+','defadsemklmonuoidday')) 38 print('+匹配前一个字符1次或多次',re.findall('y+','defadsemklmonuoidday')) 39 40 print('? 匹配前一个字符1次或0次',re.findall('mon.?day','defadsemklmon2day')) 41 print('? 匹配前一个字符1次或0次',re.findall('mon.?day','defadsemklmonday')) 42 print('? 匹配前一个字符1次或0次',re.findall('mon.?day','defadsemklmon12day')) 43 44 print(r'{m} 匹配前一个字符m次',re.findall('a{3}b','aberw')) 45 print(r'{m} 匹配前一个字符m次',re.findall('a{3}b','qweaaaberw')) 46 print(r'{m} 匹配前一个字符m次',re.findall('a{3}b','qweaaaaaaaberw')) 47 print(r'{m} 匹配前一个字符m次',re.findall('a{3}b','qweaaaaaaaberwaaab')) 48 49 print(r'{n,m} 匹配前一个字符m次',re.findall('a{1,3}b','qweaaaaaaaberwaaab'))
运行结果:
##################字符串提供的方法是完全匹配################### 2 hexxo world ['hell', ' w', 'rld'] ######################正则表达式####################### #示例: ['worl'] *****演示 . 通配符****** #完全匹配: ['monday', 'monday'] “.”默认匹配除\n之外的任意一个字符 ['worl'] 使用.匹配换行符: ['wo\nl'] *****演示 ^ 尖角符****** ^从开头匹配字符 ['monday'] ^从开头匹配字符 [] $从结尾匹配字符 ['ayaf'] $从结尾匹配字符 [] $从结尾匹配字符 [] * 重复匹配: ['monuoidday'] * 重复匹配: ['defadsemklmonuoidday', ''] * 重复匹配: ['a', 'ay'] * 重复匹配: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'y', ''] +匹配前一个字符1次或多次 ['monuoidday'] +匹配前一个字符1次或多次 ['defadsemklmonuoidday'] +匹配前一个字符1次或多次 ['ay'] +匹配前一个字符1次或多次 ['y'] ? 匹配前一个字符1次或0次 ['mon2day'] ? 匹配前一个字符1次或0次 ['monday'] ? 匹配前一个字符1次或0次 [] {m} 匹配前一个字符m次 [] {m} 匹配前一个字符m次 ['aaab'] {m} 匹配前一个字符m次 ['aaab'] {m} 匹配前一个字符m次 ['aaab', 'aaab'] {n,m} 匹配前一个字符m次 ['aaab', 'aaab'] Process finished with exit code 0
练习二:
1 #! usr/bin/env pyhton 2 # -*- coding:utf-8 -*- 3 import re 4 5 print('字符集',re.findall('a[c,d]x','acxdefa')) 6 print('字符集',re.findall('a[c,d]x','weqadxdefa')) 7 print('字符集',re.findall('[a-z]','adx')) 8 print('字符集',re.findall('a[a-z]','adx')) 9 print('字符集',re.findall('[a,,]','adx,')) 10 11 12 #[]字符集:取消元字符的特殊功能(例外: \ ^ -) 13 print('*在这里只是一个普通的字符',re.findall('[a,*]','adx')) 14 print('*在这里只是一个普通的字符',re.findall('[a,*]','adx*')) 15 print(re.findall('[1-9,a-z,A-Z]','45deWE')) 16 print('取反[^a,c]',re.findall('[^a,c]','abca,,ac')) 17 msg=r''' 18 反斜杠后面跟着普通字符实现特殊功能 19 \d====[0-9],可以匹配一个数字 20 \w可以匹配字母或数字===[0-9,a-z,A-Z] 21 \s可以匹配一个空格(也包括Tab等空白符)===[\t\n\r\f\v] 22 \S匹配任意非空字符===[^\t\n\r\f\v] 23 \w匹配数字字母下划线[a-zA-Z0-9] 24 \W匹配非数字字母下划线[^a-zA-Z0-9] 25 \b匹配一个单词边界,也就是指单词和空格间(特殊字符的边界¥)的位置。 26 例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 27 \B匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 28 29 30 ''' 31 print(msg) 32 print(re.findall('\d{11}','fadefad23142132467567585342213')) 33 print(re.findall('\wasd','def asddescfeasd')) 34 35 print(re.findall(r'I\b','I am a shuaige')) 36 print(re.findall('I\\b','I am a shuaI$ge')) 37 print(re.findall(r'I\b','hi, Iam a shuaige')) 38 print(re.findall(r'\bI','hi, Iam a shuaige')) 39 40 ''' 41 运行结果 42 43 字符集 ['acx'] 44 字符集 ['adx'] 45 字符集 ['a', 'd', 'x'] 46 字符集 ['ad'] 47 字符集 ['a', ','] 48 *在这里只是一个普通的字符 ['a'] 49 *在这里只是一个普通的字符 ['a', '*'] 50 ['4', '5', 'd', 'e', 'W', 'E'] 51 取反[^a,c] ['b'] 52 53 反斜杠后面跟着普通字符实现特殊功能 54 \d====[0-9],可以匹配一个数字 55 \w可以匹配字母或数字===[0-9,a-z,A-Z] 56 \s可以匹配一个空格(也包括Tab等空白符)===[\t\n\r\f\v] 57 \S匹配任意非空字符===[^\t\n\r\f\v] 58 \w匹配数字字母下划线[a-zA-Z0-9] 59 \W匹配非数字字母下划线[^a-zA-Z0-9] 60 \b匹配一个单词边界,也就是指单词和空格间(特殊字符的边界¥)的位置。 61 例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 62 \B匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 63 64 65 66 ['23142132467', '56758534221'] 67 ['easd'] 68 ['I'] 69 ['I', 'I'] 70 [] 71 ['I'] 72 73 74 75 '''
练习三:
1 #! usr/bin/env pyhton 2 # -*- coding:utf-8 -*- 3 import re 4 ''' 5 re.findall() 返回一个列表 6 re.search() 返回一个对象 7 8 ''' 9 ret=re.search('tom','thisistomsdest').group() 10 print(ret) 11 ret1=re.search('t.m','thisistomsdestrm') 12 print(ret1) 13 14 #现象 15 print(re.findall('\\\\','abc\de')) 16 print(re.findall(r'\\','abc\de')) 17 18 print(re.search(r'\bblow','blow').group()) 19 print(re.search('\bblow','blow')) 20 21 ''' 22 tom 23 <_sre.SRE_Match object; span=(6, 9), match='tom'> 24 ['\\'] 25 ['\\'] 26 blow 27 None 28 29 30 31 '''
练习四:
1 import re 2 3 # print('管道符 | 或'.center(50,'*')) 4 # print(re.search('(as)+','defahjgrasas').group()) 5 # print(re.search('(as)|3','3as').group()) 6 # print(re.search('(as)|3','as3').group()) 7 8 9 # ret=re.search('(?P<id>\d{3})','weeew34ttt123/ooo') 10 # print(ret) 11 # print(ret.group()) 12 # print(ret.group('id')) 13 14 ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo') 15 # print(ret) 16 print(ret.group()) 17 # print(ret.group('id')) 18 print(ret.group('name'))

1 ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo') 2 # print(ret) 3 print(ret.group()) 4 # print(ret.group('id')) 5 print(ret.group('name'))
正则表达式方法:
# re.findall() 返回一个列表
# re.search() 返回匹配到的第一个对象,如果存在返回值,可以调用group()方法
#re.match() 只在字符串开始匹配匹配,返回匹配到的第一个对象,可以调用group()方法
#re.sub()
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
1 re.match(pattern, string, flags=0)
匹配成功re.match方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 | 描述 |
---|---|
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
#!/usr/bin/python import re print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配 print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配
以上实例运行输出结果为:
(0, 3)
None
1 import re 2 3 # re.match() 只在字符串开始匹配匹配 4 ret=re.match('asd','asdfhieusjdasd') 5 print(ret.group()) 6 print(ret.span()) 7 print(ret) 8 9 10 ################################## 11 asd 12 (0, 3) 13 <_sre.SRE_Match object; span=(0, 3), match='asd'>
检索和替换
Python 的re模块提供了re.sub用于替换字符串中的匹配项。
语法:
re.sub(pattern, repl, string, count=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
#!/usr/bin/python3 import re phone = "2004-959-559 # 这是一个电话号码" # 删除注释 num = re.sub(r'#.*$', "", phone) print ("电话号码 : ", num) # 移除非数字的内容 num = re.sub(r'\D', "", phone) print ("电话号码 : ", num)
import re print(re.sub('a..t','s..b','sdfaewrasdfaatt'))
结果:
sdfaewrasdfs..b
compile 函数
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
语法格式为:
re.compile(pattern[, flags])
参数:
- pattern : 一个字符串形式的正则表达式
- flags 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
-
- re.I 忽略大小写
- re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
- re.M 多行模式
- re.S 即为' . '并且包括换行符在内的任意字符(' . '不包括换行符)
- re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
- re.X 为了增加可读性,忽略空格和' # '后面的注释
>>>import re >>> pattern = re.compile(r'\d+') # 用于匹配至少一个数字 >>> m = pattern.match('one12twothree34four') # 查找头部,没有匹配 >>> print m None >>> m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配 >>> print m None >>> m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配 >>> print m # 返回一个 Match 对象 <_sre.SRE_Match object at 0x10a42aac0> >>> m.group(0) # 可省略 0 '12' >>> m.start(0) # 可省略 0 3 >>> m.end(0) # 可省略 0 5 >>> m.span(0) # 可省略 0 (3, 5)
在上面,当匹配成功时返回一个 Match 对象,其中:
group([group1, …])
方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用group()
或group(0)
;start([group])
方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;end([group])
方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;span([group])
方法返回(start(group), end(group))
。
再看看一个例子:
>>>import re >>> pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小写 >>> m = pattern.match('Hello World Wide Web') >>> print m # 匹配成功,返回一个 Match 对象 <_sre.SRE_Match object at 0x10bea83e8> >>> m.group(0) # 返回匹配成功的整个子串 'Hello World' >>> m.span(0) # 返回匹配成功的整个子串的索引 (0, 11) >>> m.group(1) # 返回第一个分组匹配成功的子串 'Hello' >>> m.span(1) # 返回第一个分组匹配成功的子串的索引 (0, 5) >>> m.group(2) # 返回第二个分组匹配成功的子串 'World' >>> m.span(2) # 返回第二个分组匹配成功的子串 (6, 11) >>> m.groups() # 等价于 (m.group(1), m.group(2), ...) ('Hello', 'World') >>> m.group(3) # 不存在第三个分组 Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: no such group
import re # print(re.sub('a..t','s..b','sdfaewrasdfaatt')) obj=re.compile('\.com') ret=obj.findall('sdfaewrasdf.comaatt') print(ret) print(obj.match('.comsdfaewdwerwrasdf.comaatt').group()) print(obj.search('sdfaewdwerwrasdf.comaatt').group())
结果:
['.com'] .com .com
re.finditer
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
re.finditer(pattern, string, flags=0)
参数:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志 |
import re it = re.finditer(r"\d+","12a32bc43jf3") for match in it: print (match.group() )