1. 正则表达式概述
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的特定字符和这些特定字符的组合组成一个规则字符串,这个规则字符串用来表达对字符串的一种过滤逻辑。
2. 常用正则字符
模式 | 描述 | 模式 | 描述 |
---|---|---|---|
. | 匹配任意字符,除了换行符 | \s | 匹配空白字符 |
* | 匹配前一个字符0次或多次 | \S | 匹配任何非空白字符 |
+ | 匹配前一个字符1次或多次 | \d | 匹配数字,等价于[0-9] |
- | 用在[]之内表示范围 | \b | 匹配单词头或单词尾 |
? | 匹配前一个字符0次或1次 | \D | 匹配任何非数字,等价于[^0-9] |
^ | 匹配字符串开头 | \w | 匹配字母数字,等价于[A-Za-z0-9] |
$ | 匹配字符串末尾 | \W | 匹配非字母数字,等价于[^A-Za-z0-9] |
() | 匹配括号内的表达式,也表示一个组 | [] | 用来表示一组字符 |
{} | 按{}中的次数进行匹配 | [^xyz] | 反字符集,匹配除x、y、z以外的任何字符 |
[a-z] | 字符范围 | [^a-z] | 反向字符范围 |
更多细则详见python官网正则表达式文档……
3. re模块的一些方法
- re模块中python正则表达式的方法
方法 | 功能说明 |
---|---|
compile(pattern[,flags]) | 创建模式对象 |
search(pattern,string[,flags]) | 在整个字符串中寻找模式,返回match对象或None |
match(pattern, string[,flags]) | 从字符串的开始处匹配模式,返回match对象或None |
findall(pattern, string[flags]) | 列出字符串中模式的所有匹配项 |
split(pattern,string[,maxsplit=0]) | 根据模式匹配项分割字符串 |
sub(pat,repl,string[,count=0]) | 将字符串中所有pat的匹配项用repl替换 |
escape(string) | 将字符串中所有特殊正则表达式字符转义 |
- match对象的主要方法有:group()、groups()、groupdict()、start()、end()、span()
- 其中,函数参数flags的值可以是re.I(忽略大小写)、re.L、re.M(多行匹配模式)、re.S(使元字符“.”匹配任意字符,包括换行符)、re.U(匹配Unicode字符)、re.X(忽略模式中的空格,并可以使用#注释)的不同组合(使用“|”进行组合)。
①re.match(pattern, string, flags=0)
从字符串起始位置匹配一个模式,如果起始位置匹配不了,那么返回 None
其中:pattern 是正则表达式,包含一些特殊的字符;string 为要匹配的字符串;flags 用来控制正则表达式的匹配方式,如是否区分大小写、多行匹配等。
>>> line = '12324111'
>>> re.match('2', line)
>>> import re
>>> line = '12324111'
>>> result = re.match('2', line)
>>> print(result)
None
>>> line = 'www.baidu.com'
>>> result = re.match('www', line)
>>> print("匹配的结果:{0}\n匹配的起始与终点:{1}\n匹配的起始位置:{2}\n匹配的终点位置:{3}".format(result, result.span(), result.start(), result.end()))
匹配的结果:<re.Match object; span=(0, 3), match='www'>
匹配的起始与终点:(0, 3)
匹配的起始位置:0
匹配的终点位置:3
进一步将pattern改成正则表达式:
>>> line = 'Life is short, I learn python.'
>>> m = re.match('(.*), (.*) python', line)
>>> print('匹配的整句话: {0}\n匹配的第一个结果:{1}\n匹配的结果列表:{2}'.format(m.group(0), m.group(1), m.groups()))
匹配的整句话: Life is short, I learn python
匹配的第一个结果:Life is short
匹配的结果列表:('Life is short', 'I learn')
注:此处pattern采用raw string的形式表示,可以避免对反斜杠“\”进行转义~
②re.search
与match只能从字符串起始位置进行扫描不同,research扫描整个字符串并返回第一个成功的匹配~
>>> line = 'www.baidu.com'
>>> r_match = re.match('com', line)
>>> r_search = re.search('com', line)
>>> print(r_match)
None
>>> print(r_search)
<re.Match object; span=(10, 13), match='com'>
>>> line = '4321\n5678\n4567\r\n456'
>>> re.search(r'6(.*)', line)
<re.Match object; span=(6, 9), match='678'>
③re.findall
上述 match 和 search 方法只能找到一个匹配所写的模式,而 findall 可以找到所有的匹配,并以列表形式返回
>>> line = '1234\n5678\n4567\r\n456'
>>> m = re.findall(r'[0-9]+', line)
>>> print(m)
['1234', '5678', '4567', '456']
应用:当爬取博客文章时,如果提取的不只是一个标题,而是所有标题,就可以使用 findall
4. 更多
另外还可在 Regular Expression 101 网站学习更多的正则表达式~
5. 练习
匹配位于[]内的任意一个字符
>>> ls = 'heypythonhellojythonworldcython'
>>> re.findall('[pjc]ython',ls)
['python', 'jython', 'cython']
反向字符集,匹配除此之外的任何字符集
>>> ls = 'abcabcaamsdhjk'
>>> re.search('[^abc]',ls)
<re.Match object; span=(8, 9), match='m'>
匹配位于|之前或之后的字符
>>> ls = 'happyaniceday'
>>> re.search('excellent|nice',ls)
<re.Match object; span=(6, 10), match='nice'>
匹配位于*之前的字符或子模式0次或多次
>>> ls = 'abcdefmmm'
>>> re.match('abcdef[0-9]*',ls)
<re.Match object; span=(0, 6), match='abcdef'>
利用{}指定字符串长度匹配,[0-9]等价于\d
>>> ls = '1234abd567sd98879'
>>> re.findall('[0-9]{3,}', ls)
['1234', '567', '98879']
>>> re.findall('\d{3,}', ls)
['1234', '567', '98879']
-------------------------------
>>> ls = 'this123happy89_day'
>>> re.findall('[a-z]{4}', ls)
['this', 'happ']
\s匹配任何空白字符,与[ \f\n\r\t\v]等效
>>> ls = 'ohhhh how\nto\rdone'
>>> re.findall('\s', ls)
[' ', '\n', '\r']
\w匹配任何字母、数字以及下划线,等价于[a-zA-Z0-9_]
>>> ls = '123asD Hei233_~'
>>> re.findall('\w', ls)
['1', '2', '3', 'a', 's', 'D', 'H', 'e', 'i', '2', '3', '3', '_']
>>> re.findall('\w+', ls)
['123asD', 'Hei233_']
匹配单词,\b表示匹配单词头或单词尾
>>> ls = 'shanghai is a modern city'
>>> pattern = re.compile(r'\bm\w+\b')
>>> pattern.search(ls)
<re.Match object; span=(14, 20), match='modern'>
匹配给定字符串中所有汉字
>>> ls = 'lalala今天o是个好天气hhh'
>>> re.findall('[\u4e00-\u9fa5]', ls)
['今', '天', '是', '个', '好', '天', '气']
>>> re.findall('[\u4e00-\u9fa5]+', ls)
['今天', '是个好天气']
使用re模块的方法实现的操作
>>> import re
>>> text = 'alpha.beta....gamma delta'
>>> re.split('[\. ]', text)
['alpha', 'beta', '', '', '', 'gamma', 'delta']
>>> re.split('[\. ]', text, maxsplit=2) #分割两次
['alpha', 'beta', '...gamma delta']
>>> re.split('[\. ]+', text)
['alpha', 'beta', 'gamma', 'delta']
>>> re.split('[\. ]+', text, maxsplit=2)
['alpha', 'beta', 'gamma delta']
>>> pat = '{name}'
>>> text = 'Dear {name}...'
>>> re.sub(pat, 'Mr.Dong', text) #字符串替换
'Dear Mr.Dong...'
>>> s = 'a s d'
>>> re.sub('a|s|d', 'good', s) #字符串替换
'good good good'
>>> re.escape('http://www.python.org') #字符串转义
'http://www\\.python\\.org'
去除字符串的多余空格
>>> import re
>>> s = 'aaa bb c d e ff '
>>> re.sub('\s+', ' ', s) #直接使用re模块的字符串替换方法
'aaa bb c d e ff '
>>> re.split('[\s]+', s)
['aaa', 'bb', 'c', 'd', 'e', 'ff', '']
>>> re.split('[\s]+', s.strip()) #同时删除字符串尾部空格
['aaa', 'bb', 'c', 'd', 'e', 'ff']
>>> ' '.join(re.split('[\s]+', s.strip()))
'aaa bb c d e ff'
>>> re.sub('\s+', ' ', s.strip())
'aaa bb c d e ff'
>>> ' '.join(s.split()) #或不使用正则,直接split配join
'aaa bb c d e ff'
>>> import re
>>> example = 'ShanDong Institute of Business and Technology is a very beautiful school.'
>>> re.findall('\\ba.+?\\b', example) #以a开头的完整单词
['and', 'a ']
>>> re.findall('\\ba\w*\\b', example)
['and', 'a']
>>> re.findall('\\Bo.+?\\b', example) #含有o字母的单词中第一个非首字母o的剩余部分
['ong', 'ology', 'ool']
>>> re.findall('\\b\w.+?\\b', example) #所有单词
['ShanDong', 'Institute', 'of', 'Business', 'and', 'Technology', 'is', 'a ', 'very', 'beautiful', 'school']
>>> re.findall(r'\b\w.+?\b', example) #使用原始字符串,减少需要输入的符号数量
['ShanDong', 'Institute', 'of', 'Business', 'and', 'Technology', 'is', 'a ', 'very', 'beautiful', 'school']
>>> re.split('\s', example) #使用任何空白字符分割字符串
['ShanDong', 'Institute', 'of', 'Business', 'and', 'Technology', 'is', 'a', 'very', 'beautiful', 'school.']
>>> re.findall('\d\.\d\.\d+', 'Python2.7.11') #查找并返回x.x.x形式
['2.7.11']
>>> re.findall('\d\.\d\.\d+', 'Python2.7.11,Python3.5.1')
['2.7.11', '3.5.1']
使用正则表达式对象
>>> import re
>>> example = 'Shanghai Institute of Business and Technology'
>>> pattern = re.compile(r'\bB\w+\b') #匹配以B开头的单词
>>> pattern.findall(example)
['Business']
>>> pattern = re.compile(r'\w+g\b') #以g结尾的单词
>>> pattern.findall(example)
[]
>>> pattern = re.compile(r'\w+i\b')
>>> pattern.findall(example)
['Shanghai']
>>> pattern = re.compile(r'\b[a-zA-Z]{3}\b') #查找三个字母长的单词
>>> pattern.findall(example)
['and']