字符串操作可以匹配一些数据,如想判断一个字符串中是否包含'python',可以用str.find()、str.index(),但是要想查找符合某种规则的数据,比如要匹配以字母开头,数字结尾的邮箱名称,字符串操作并不能满足,这时候就需要依靠正则表达式。
正则表达式,又称规则表达式。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。通过正则表达式操作可以判断字符串是否匹配某个规则,以及可以从字符串中提取匹配某种规则的数据。很多程序设计语言都支持利用正则表达式进行字符串操作,以python为例,在python中使用正则表达式要引入re模块。
re模块
一般的字符串也是一个正则表达式,可以匹配包含自身的字符串。
>>> import re
>>> re.search(r'pen','I have a pen')
<_sre.SRE_Match object; span=(9, 12), match='pen'>
有一些特殊的元字符,如. ^ $ * + ? { } [ ] \ | ( )它们不能匹配自身,而是用于定义字符类、重复次数等等。
.表示匹配除了换行符外的任何字符
>>> re.search(r'.','I did not eat yesterday')
<_sre.SRE_Match object; span=(0, 1), match='I'>
{M,N}表示前边的RE匹配M~N次,M和N均为非负整数,其中M<=N
>>> re.search(r'ab{3}c','abbbc')
<_sre.SRE_Match object; span=(0, 5), match='abbbc'>
>>> re.search(r'ab{3}c','abbbbc')
>>> re.search(r'ab{3,10}c','abbbbc')
<_sre.SRE_Match object; span=(0, 6), match='abbbbc'>
*匹配前面的子表达式零次或多次,等价于 {0,}
>>> re.search(r'ab*c','abbbc')
<_sre.SRE_Match object; span=(0, 5), match='abbbc'>
>>> re.search(r'ab*c','ac')
<_sre.SRE_Match object; span=(0, 2), match='ac'>
+匹配前面的子表达式一次或多次,等价于 {1,}
>>> re.search(r'ab+c','ac')
>>> re.search(r'ab+c','abc')
<_sre.SRE_Match object; span=(0, 3), match='abc'>
>>> re.search(r'ab+c','abbc')
<_sre.SRE_Match object; span=(0, 4), match='abbc'>
?匹配前面的子表达式零次或一次,等价于 {0,1}
>>> re.search(r'ab?c','abbc')
>>> re.search(r'ab?c','ac')
<_sre.SRE_Match object; span=(0, 2), match='ac'>
>>> re.search(r'ab?c','abc')
<_sre.SRE_Match object; span=(0, 3), match='abc'>
[]字符类,匹配所包含的任意一个字符
>>> re.search(r'[aeiou]','I have 23 books')
<_sre.SRE_Match object; span=(3, 4), match='a'>
[aeiou]表示匹配aeiou中任意一个字符
>>> re.search(r'[a-z]','I have 23 books')
<_sre.SRE_Match object; span=(2, 3), match='h'>
[a-z]表示匹配任意一个小写字母
>>> re.search(r'[0-9]','I have 23 books')
<_sre.SRE_Match object; span=(7, 8), match='2'>
[0-9]表示匹配任意一个数字
>>> re.search(r'[A-Za-z0-9]','I have 23 books')
<_sre.SRE_Match object; span=(0, 1), match='I'>
[A-Za-z0-9]表示匹配任意一个字母或数字
[^a] 表示匹配字符集之外的字符
>>> re.search(r'[^A-Za-z0-9]','I have 23 books')
<_sre.SRE_Match object; span=(1, 2), match=' '>
该字符串除了数字和字母,只能匹配到空格
A | B,表示匹配正则表达式 A 或者 B
>>> re.search(r'D|different','different')
<_sre.SRE_Match object; span=(0, 9), match='different'>
贪婪匹配
如果用.+会尽量匹配到最后一个字符,但是加上?时会在匹配到第一处之后不继续匹配
>>> re.search(r'.+','Today is Friday')
<_sre.SRE_Match object; span=(0, 15), match='Today is Friday'>
>>> re.search(r'.+?','Today is Friday')
<_sre.SRE_Match object; span=(0, 1), match='T'>
>>> re.search(r'<.+>',s)
<_sre.SRE_Match object; span=(0, 43), match='Today is Friday '>
>>> re.search(r'<.+?>',s)
<_sre.SRE_Match object; span=(0, 6), match=''>
匹配数字
>>> re.search(r'\d','I have 23 books')
<_sre.SRE_Match object; span=(7, 8), match='2'>
>>> re.search(r'\d\d','I have 23 books')
<_sre.SRE_Match object; span=(7, 9), match='23'>
匹配IP地址
199怎么匹配,[1-999]?显然不是,观察IP地址特性,我们发现1开头的话从1-199,2开头最高只能到255
>>> re.search(r'[01]\d\d|2[0-4]\d|25[0-5]','199')
<_sre.SRE_Match object; span=(0, 3), match='199'>
>>> re.search(r'[01]\d\d|2[0-4]\d|25[0-5]','239')
<_sre.SRE_Match object; span=(0, 3), match='239'>
等等,IP地址可以是1.1.1.1噢,但是目前一位数的好像匹配不到
>>> re.search(r'[01]\d\d|2[0-4]\d|25[0-5]','1')
前两位数需要加上可选
>>> re.search(r'[01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5]','1')
<_sre.SRE_Match object; span=(0, 1), match='1'>
IP地址是四个号段,可以用上()子组避免重复太多
>>> re.search(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])','192.168.1.1')
<_sre.SRE_Match object; span=(0, 11), match='192.168.1.1'>
还有很多特殊符号使正则表达式变得强大。除了search方法,re模块还有其他使用方式。
获得匹配项
>>> re.findall(r'[a-z]','fishCfishC')
['f', 'i', 's', 'h', 'f', 'i', 's', 'h']
编译正则表达式
>>> p=re.compile(r'[a-z]')
>>> type(p)
>>> p.search('have')
<_sre.SRE_Match object; span=(0, 1), match='h'>
>>> p.findall('Have')
['a', 'v', 'e']
应用
判断字符串匹配
当字符串匹配某个模式时,执行xx操作
>>> p='192.168.1.2'
>>> if re.match(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])',p):
print('It is IP address.')
It is IP address.
>>> p='256.256.1.2'
>>> if re.match(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])',p):
print('It is IP address.')
>>>
提取某字段
如提取字符串中的 URL
>>> url = re.findall('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', 'http://www.baidu.com,https://www.jianshu.com/u/72482eeda813')
>>> url
['http://www.baidu.com', 'https://www.jianshu.com']
正则表达式的主要应用有:
1、校验用户输入信息是否符合手机号、电话号码、邮箱、年龄等格式。需要用户手动输入信息的时候,为了避免后续数据处理问题,需要用正则表达式进行基本校验。
2、在爬虫时可能需要从页面中获取特定格式的数据(提取URL、IP地址等等),也需要用正则表达式进行处理。