一、用正则表达式查找文本模式
正则表达式,简称regex,是文本模式的描述方法。比如\d是一个正则表达式,用于表示一位0~9的数字。在一个模式后面加上花括号包围的数字n(如{n}),表示匹配这个模式n次。
1、创建正则表达式对象
Python中的正则表达式位于re模块中。
向re.compile()传入一个字符串值,表示正则表达式,将返回一个Regex模式对象。
1 import re 2 phoneNumberRegex=re.compile(r'\d\d\d-\d{8}')
上述代码创建一个用于匹配电话号码的正则表达式。
2、匹配Regex对象
Regex对象有一个search()方法查找传入的字符串,寻找与该正则表达式相匹配的所有内容。
如果找到了匹配的内容,search()方法会返回一个Match对象,该对象包含一个group()方法,会返回被查找字符串中相匹配的文本。
如果没有找到匹配的内容,则返回None。
1 mr = phoneNumberRegex.search('My phone number is 555-66668888.') 2 print(mr.group())
示例:
1 import re 2 phone_number_regex = re.compile(r'\d{3}-\d{3}-\d{4}') #{3}表示这个表达式匹配3次 3 mo = phone_number_regex.search('My number is 515-555-5555') 4 print('Phone number found:'+ mo.group()) 5 print(type(mo)) #mo是一个Match对象,需要调用group()方法才会打印实际匹配到的文本
>>>Phone number found:515-555-5555
3、用正则表达式匹配更多模式
(1)利用括号分组
添加括号将在正则表达式中创建分组,如(\d\d\d)-(\d\d\d\d-\d\d\d\d),然后可以利用group()方法从分组中获得匹配的文本。向group()方法中传入整数参数,则返回与参数对应的分组内容,如果传入0或者不传参数,则默认返回全部文本。如果想要一次获取全部分组,可以使用groups()方法,该方法返回一个元组,其中包含所有的分组。
1 import re 2 3 phone_number_regex = re.compile(r'(\d{3})-(\d{3}-\d{4})') 4 mo = phone_number_regex.search('My number is 515-555-5555') 5 print(mo.group(1)) 6 print(mo.group())
7 print(mo.groups())
>>>
515
515-555-5555
('515', '555-5555')
注意:正则表达式中的原始字符串 r 对括号 ( ) 没有作用,如果想匹配括号,必须用 \ 进行转义。
(2)用管道符 | 匹配多个分组
比如:正则表达式 r'Batman|Tina Fey' 将匹配‘Batman’或者‘Tina Fey’。 如果两个内容同时出现在被查找的内容中,则返回第一次出现的匹配文本。
1 import re 2 hero_regex = re.compile(r'Batman|Tina Fey') 3 mo1 = hero_regex.search('Batman and Tina Fey') 4 print(mo1.group())
>>> Batman
如果想要匹配的内容有相同的前缀,则可以用管道符将后缀组合起来。
1 import re 2 bat_regex = re.compile(r'Bat(man|mobile|copter|bat)') 3 mo1 = bat_regex.search('Batmobile lost a wheel') 4 print(mo1.group()) #返回完全匹配的文本Batmobile 5 print(mo1.group(1)) #只返回括号分组内匹配的文本mobile
>>>
Batmobile
mobile
(3)用问号实现可选匹配
字符 ? 表明它前面的分组在这个模式中是可选的,即匹配0次或者1次。
比如 r'Bat(wo)?man' 将匹配 ‘Batman’ 和 ‘Bat(wo)man’
(4)用星号 * 匹配0次或者多次
比如 r'Bat(wo)*man' 将匹配 ‘Batman’ 和 ‘Batwoman’以及'Batwowowowo.......man'
(5)用加号 +匹配一次或者多次
比如 r'Bat(wo)*man' 将匹配 ‘Batwoman’以及'Batwowowowo.......man'
(6)用花括号 { } 匹配特定次数
比如 (Ha){3} 将匹配 ‘HaHaHa’
另外花括号还可以指定一个范围,比如{3,5},{3,},{,5}
4、贪心匹配和非贪心匹配
Python的正则表达式默认在有二义的情况下匹配尽可能长的字符,比如{3,5},如果可以匹配5次,就默认匹配5次。如果想要设置非贪心匹配,则在花括号后面加上?,即{3,5}?,则匹配最少的次数。
5、findall() 方法
search方法返回一个对象,包含被查找字符串中的‘第一次’匹配的内容。而findall方法将以列表的形式返回一组字符串,包含被查找的字符串中所有匹配的内容。
1 import re 2 3 phone_numbre_regex = re.compile(r'\d{3}-\d{3}-\d{4}') #未分组 4 phone_number = phone_numbre_regex.findall('Cell:555-555-5555 Work:888-888-8888') 5 print(phone_number) 6 7 phone_numbre_regex = re.compile(r'(\d{3})-(\d{3}-\d{4})') #有分组 8 phone_number = phone_numbre_regex.findall('Cell:555-555-5555 Work:888-888-8888') 9 print(phone_number) >>> ['555-555-5555', '888-888-8888'] [('555', '555-5555'), ('888', '888-8888')]
注意:如果调用的是一个没有分组的正则表达式,findall将返回一个匹配字符串的列表;如果调用的是一个有分组的正则表达式,findall方法返回的是一个字符串的元组的列表,因为分组匹配到的内容会放在元组中传递给列表。
6、字符分类
字符分类 | 表 示 |
\d | 0到9的任何数字 |
\D | 除0到9的数字以外的任何字符 |
\w | 任何字母、数字或下划线字符(看做是匹配‘单词’字符) |
\W | 除字母、数字和下划线以外的任何字符 |
\s | 空格、制表符或换行符(看做是匹配‘空白’字符) |
\S | 除空格、制表符和换行符以外的任何字符 |
字符分类一般用于压缩正则表达式,比如[0-5]只匹配数字0-5,比输入(0|1|2|3|4|5) 要方便很多。
7、建立自己的字符分类
(1)可以用方括号定义自己的字符分类。
比如:
[aeiouAEIOU]用于匹配所有的元音字母。
(2)可以使用短线 — 表示字母或者数字的范围
比如:
[a-zA-Z0-9] 将匹配所有的小写字母、大写字母和数字
(3)在方括号中的普通正则表达式不会被解释,也就是说不需要用反斜线进行转义。
比如:
[0-5.] 将用于匹配数字0-5和一个句点,而句点不需要进行转义。
(4)通过在字符分类的左方括号后面加上一个插入字符( ^ )就可以得到‘非字符类’ 。非字符分类将匹配不在这个字符分类中的所有字符。
8、插入字符和美元字符
可以在正则表达式的开始处使用插入符号(^)表明匹配必须发生在被查找文本的开始处;
可以在正则表达式的末尾处使用美元符号($)表明该字符串必须以这个正则表达式的模式结束;
可以同时使用上述两个字符,表明整个字符串必须完全匹配该正则表达式。
注意:这里的插入符用法和字符分类中插入符用法的不同。
9、通配字符
在正则表达式中,句点(.)表示匹配除换行符之外的所有字符,但是句点只匹配一个字符,可以和前面的多次匹配相结合使用,比如( .* )匹配任意多个非换行字符。
1 import re 2 bat_Regex = re.compile(r'.*') 3 mo_1 = bat_Regex.search('The Adventures \n of Batwowowoman') 4 print(mo_1.group())
>>>The Adventures
如果想要句点字符可以匹配换行符,可以通过传入re.DOTALL作为re.compile()的第二个参数
1 import re 2 bat_Regex = re.compile(r'.*',re.DOTALL) 3 mo_1 = bat_Regex.search('The Adventures \n of Batwowowoman') 4 print(mo_1.group())
>>>
The Adventures
of Batwowowoman
10、不区分大小写的匹配
可以通过传入 re.I (IGNORECASE) 作为re.compile()的第二个参数,使匹配字符的时候忽略大小写
11、用sub()方法替换字符串
Regex对象的sub() 方法需要传入两个参数,第一个参数是一个字符串,用于取代发现的匹配,第二个字符串是一个字符串,使用正则表达式匹配的内容。sub() 方法返回替换完后的字符串。
12、管理复杂的正则表达式
可以通过传入re.VERBOSE 作为re.compile()的第二个参数,这样就可以忽略被正则表达式中的空白符和注释
1 import re 2 3 name_regex = re.compile(r''' 4 ([a-z]*) #匹配任意多个字母,不区分大小写 5 (\n) #匹配一个换行符 6 ([0-9]*) # 匹配任意多个数字 7 ''',re.I|re.DOTALL|re.VERBOSE) 8 # 末尾加上 re.I 表示忽略大小写; re.DOTALL 表示让句点字符‘.’也能匹配换行; re.VERBOSE表示在正则表达式中使用注释。 9 answer_1= name_regex.search('abcdABCD\n8097809') 10 print(answer_1.group())
>>>
abcdABCD
8097809
注意:如果想要正则表达式忽略大小写,并且匹配换行符,同时还要忽略空白符和注释,可以向re.compile() 的第二个参数同时传入 re.I 、re.VERBOSE 、re.DOTALL ,用管道符连接起来即可。