第十六章 常用模块-正则表达式
1 正则表达式概述
1.1 什么是正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
正则表达式的唯一作用就是 匹配验证 字符串
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
正则表达式就像“医生的字”、“道士的符”、“女人的心”,看也看不懂
1.2 正则表达式应用
- 验证邮箱、验证用户名是否符合规范、验证密码是否符合规范、验证电话号码 等
- UBB编辑器、富文本编辑器、聊天表情的替换
- 爬虫: 利用正则提取爬到的数据
1.3 正则表示式学习过程
第一, 掌握正则表达式的语法,学会如何书写正则表达式
第二,使用Python内建的re模块使用正则表达式
2 正则表达式语法
2.1 原子
原子是正则表达式最小组成单位, 正则表达式 就是 由原子和对原子的修饰组成
① 字符直接量
每个字母和数字以及没有特殊含义的符号都是原子,这种原子匹配的就是他们自身
② 转义字符
模式 | 描述 |
---|---|
\n |
换行符 |
\t |
制表符 |
\v |
垂直制表符 |
\r |
回车符 |
\f |
换页符 |
\0 |
匹配NUL字符 |
\uxxxx |
unicode字符 |
注: 中文字的unicode范围为
/u4e00
-/u9fa5
③ 字符类
模式 | 描述 |
---|---|
[...] |
用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k', [a-z] 匹配所有的小写字母 |
[^...] |
不在[]中的字符:abc 匹配除了a,b,c之外的字符 |
\d |
匹配所有的数字 [0-9] |
\D |
匹配非数字 [^0-9] |
\w |
匹配数字、字母、下划线 [a-zA-Z0-9_] |
\W |
匹配除了数字、字母、下划线 [^a-zA-Z0-9] |
\s |
匹配任意空白字符 [\n\r\t\v\f] |
\S |
匹配任意非空字符 [^\n\r\t\v\f] |
. |
匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符 |
④ 模式单元
()
可以声明一个模式单元,每个模式单元都被当做一个原子。 ()
可以把多个原子当做一个原子. 如
"(hello){1,3}"
⑤ 特殊原子
正则表达式中有许多符号具有特殊意义,如.
、?
、*
等,要匹配这样的字符,可以使用\
进行转义
re.match('\.', '.txt')
re.match('\\\\', '\lesson\data.txt')
re.match(r'\\', '\lesson\data.txt')
2.2 原子数量修饰
模式 | 描述 |
---|---|
{n} |
前面原子的数量 n次 |
{n,} |
前面原子的数量n次以及以上 |
{n,m} |
前面原子的数量n次到m次 |
? |
前面原子的数量 0次或 1次 {0,1} |
+ |
前面原子的数量1次或多次 {1,} |
* |
前面原子的数量0次、1次或多次也就是任意次 {0,} |
后面加
?
可以阻止贪婪匹配。 默认会尽可能多的匹配,故称之为贪婪匹配
2.3 原子位置修饰
模式 | 描述 |
---|---|
\b |
匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er' |
\B |
匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er' |
\A |
匹配字符串开始 |
\Z |
匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串 |
^ |
匹配字符串的开头 同\A |
$ |
匹配字符串结束 同\Z |
(?=) |
先行断言(正向预查) |
(?!) |
负向先行断言(负向预查) |
2.4 模式单元
"(\w{3})"
- 改变优先级
- 将多个原子视为一个原子
- 将匹配的内容暂存在内存,形成一个个小组
- 可以将括号的内容在
re.sub()
的辅助下反向引用。使用\1
、\2
可以反向引用,\1
会引用第一个模式单元匹配的内容 (?:abc)
用问号冒号,可以取消暂存内存的特性(?imx: ...)
只在在括号中使用i, m, 或 x 可选标志,(?i:...)
、(?m:...)
、(?ix:...)
任意标志组合都可以(?-imx:...)
在括号中不使用i, m, 或 x 可选标志
2.5 选择修饰符
|
修饰符类似于逻辑或
"a|b" # 匹配a或者b
"abc|def" # 匹配abc 或者def 字符串的结合优先级高于选择
"ab(c|d)ef" # 匹配abcef 或者abdef
2.6 注释
"(?#注释)\w{2,6}"
3 re模块
3.1 re 模块方法
re.match() 和 re.search()
re.match()
和re.search()
是最常用的用正则匹配字符串的两个方法,用法如下:
re.match(pattern, string, flags=0) # 匹配成功re.match方法返回一个匹配的对象 否则返回None
re.search(pattern, string, flags=0) # 扫描整个字符串并返回第一个成功的匹配 否则返回None
"""
参数:
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式
"""
二者用法类似,但是存在区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
而re.search匹配整个字符串,直到找到一个匹配。
这两个方法,匹配成功,都返回一个 _sre.SRE_Match
对象,改对象有如下方法
matchObj.group() # 匹配的整个表达式的字符串
matchObj.group(1) # 返回第一个模式单元匹配的内容,数字指定几就是第几个模式单元匹配的内容
matchObj.groups() # 返回元祖,内容是模式单元匹配的内容
matchObj.span() # 返回一个元组包含匹配 (开始,结束) 的位置
matchObj.start() # 返回匹配开始的位置
matchObj.end() # 返回匹配结束的位置
re.sub()
re模块提供了re.sub用于替换字符串中的匹配项,语法如下
re.sub(pattern, repl, string, count=0)
"""
参数
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
"""
import re
phone = "2004-959-559 # 这是一个电话号码"
# 删除注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)
# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print ("电话号码 : ", num)
import re
# 利用 模式单元的引用
content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
content=re.sub('(\d+)(\s)(\d+)',r'\3\2\1',content)
print(content)
import re
# 将匹配的数字乘于 2
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
re.findall()
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
match 和 search 是匹配一次 findall 匹配所有。
re.findall(pattern, string, flags=0)
"""
参数:
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式
"""
re.finditer()
和re.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() )
# 迭代出来的变量是 _sre.SRE_Match 对象
re.split()
split 方法按照能够匹配的子串将字符串分割后返回列表,语法如下
re.split(pattern, string[, maxsplit=0, flags=0])
'''
参数
pattern 匹配的正则表达式
string 要匹配的字符串。
maxsplit 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
flags 标志位,用于控制正则表达式的匹配方式,
'''
re.compile()
re.compile()
函数用于编译正则表达式,生成一个正则表达式( SRE_Pattern )对象
该对象可作为 re.match()
、re.search()
、re.sub()
、re.split()
、re.finditer()
、re.findall()
的第一个参数
语法如下
re.compile(pattern[, flags])
"""
参数
pattern : 一个字符串形式的正则表达式
flags 可选,表示匹配模式,比如忽略大小写,多行模式等,
"""
3.2 SRE_Pattern 对象
pattern.match(string[, pos[, endpos]])
pattern.search(string[, pos[, endpos]])
pattern.sub(repl, string, count)
pattern.findall(string[, pos[, endpos]])
pattern.finditer(string[, pos[, endpos]])
pattern.split(string, maxsplits)
"""
参数
pos 可选参数,指定字符串的起始位置,默认为 0。
endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
"""
import re
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小写
m = pattern.match('Hello World Wide Web')
L = pattern.findall('dandan love me')
3.3 正则标识符
修饰符 | 描述 |
---|---|
re.I |
使匹配对大小写不敏感 |
re.L |
做本地化识别(locale-aware)匹配 python3.6起删除 |
re.M |
多行匹配,影响 ^ 和 $ |
re.S |
使 . 匹配包括换行在内的所有字符 |
re.U |
根据Unicode字符集解析字符。这个标志影响 \w , \W , \b , \B Python3已经删除 |
re.X |
该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解,忽略正则中的空格 |
re.A |
让 \w , \W , \b , \B , \d , \D , \s and \S 执行纯 ASCII 匹配,而不是全部Unicode匹配 |
re.search('a', 'Abcdef', re.I)
re.search('^a', 'bc\nAde', re.I|re.M) # 指定多个标志位
re.search('\w', '你好聪明啊', re.A)