正则表达式
动机:
1. 处理文本称为计算机常见工作之一
2. 对文本内容的搜索提取是一项比较复杂困难的工作
3. 为了方便快速处理上述问题,正则表达式技术诞生,逐渐发展为一个被众多语言使用的独立技术
定义: 即高级文本匹配模式,提供了搜索,替代等功能。本质是由一系列特殊符号和字符组成的字串,这个字串即是正则表达式。
这个表达式描述了字符和字符的重复行为,可以匹配某一类特征的字符串。
目标:
1. 熟练使用正则表达式符号
2. 能够正确的组合和理解一般的正则表达式
3. 能够使用python操作正则表达式
正则表达式特点:
1. 方便进行检索和修改
2. 支持语言众多
3. 灵活多样
mongo正则类型,django等框架作为url匹配,爬虫
正则表达式的使用
Python ==> re python中专门处理正则表达式的模块re
re.findall(pattern, string)
功能: 使用正则表达式匹配字符串
参数: pattern 正则表达式
string 目标字符串
返回值: 一个列表,匹配到的内容
In [1]: s = 'My email is lvze@tedu.cn'
In [2]: import re
In [3]: re.findall('\w+@\w+\.cn',s)
Out[3]: ['lvze@tedu.cn']
元字符: 即正则表达式中有特殊含义的符号
import re
1. 普通字符
元字符: abc
匹配规则: 匹配相应的普通字符
In [6]: re.findall('abc', 'abcdsajkdhjabcdfjlks')
Out[6]: ['abc', 'abc']
2. 或
元字符: ab|cd
匹配规则: 匹配|两边任意一个正则表达式符合的情况
In [7]: re.findall('ab|cd', 'abcdsajkdhjabcdfjlks')
Out[7]: ['ab', 'cd', 'ab', 'cd']
In [8]: re.findall('ab|bc', 'abcdsajkdhjabcdfjlks')
Out[8]: ['ab', 'ab']
* |两侧不要有没用的空格
* 匹配部分不能重叠 即第一个匹配到内容与第二个有重叠部分,第二个则无法再匹配到
3. 匹配单一字符
元字符: .
匹配规则: 匹配除了换行之外的任意字符
In [10]: re.findall('.', 'ab\n,5.')
Out[10]: ['a', 'b', ',', '5', '.']
* \n是无法匹配到的
In [11]: re.findall('你.', '你们吃饭了吗')
Out[11]: ['你们']
4. 匹配开头位置
元字符: ^
匹配规则: 匹配一个字符串的开始位置
In [12]: re.findall('^hello', 'hello world!hello')
Out[12]: ['hello']
* 必须在目标字符串的开头位置才能匹配到
5. 匹配结束位置
元字符: $
匹配规则: 匹配目标字符串的结束位置
In [13]: re.findall('hello$', 'hello world!hello')
Out[13]: ['hello']
* 只能匹配到最后以hello结尾的,第一个hello是无法匹配到的
6. 匹配重复
元字符: *
匹配规则: 匹配前面的正则表达式重复0次或多次
fo* ==> fo foo fooooooo f
In [15]: re.findall('ab*', 'abdshjbabbbbbdsa')
Out[15]: ['ab', 'abbbbb', 'a']
* '*'前面的字符出现重复0次或多次都可以匹配到
7. 匹配重复
元字符: +
匹配规则: 匹配前面的正则表达式重复1次或多次
In [17]: re.findall('ab+', 'abdshjbabbbbbdsa')
Out[17]: ['ab', 'abbbbb']
* '+'前面的字符出现至少出现一次
8. 匹配重复
元字符: ?
匹配规则: 匹配前面的正则表达式重复0次或者1次
In [18]: re.findall('ab?', 'abdshjbabbbbbdsa')
Out[18]: ['ab', 'ab', 'a']
* '?'前面的字符出现0次或者1次
9. 匹配重复
元字符: {n}
匹配规则: 匹配固定的重复次数
In [20]: re.findall('ab{2}', 'abdshjbabbbbbdsa')
Out[20]: ['abb']
* {n}匹配到前面字符出现的个数的内容
10. 匹配重复
元字符: {m, n}
匹配规则: 匹配前面的正则表达式重复 m次 到 n次
ab{3,5} abbb abbbb abbbbb
11. 匹配字符集合:
元字符: [...]
匹配规则: 匹配[]范围内的任意一个字符
[132sa] 1,3,2,s,a
[a-z] [A-Z] [0-9]
[123a-zA-Z]
In [3]: re.findall('[2a-z]','dsaD123s')
Out[3]: ['d', 's', 'a', '2', 's']
* 可以组合使用
12. 匹配字符集合
元字符: [^...]
匹配规则: 匹配除指定字符集之外的任意字符
In [4]: re.findall('[^2a-z]','dsaD123s')
Out[4]: ['D', '1', '3']
13. 匹配任意(非)数字字符
元字符: \d \D
匹配规则: \d匹配任意数字字符 \D匹配任意非数字字符
[0-9] [^0-9]
In [6]: re.findall('1\d{10}','18562663566')
Out[6]: ['18562663566']
In [7]: re.findall('\D+','hello 123')
Out[7]: ['hello ']
14. 匹配(非)普通字符 (普通字符: 数字 字母 下划线)
元字符: \w \W
匹配规则: \w 匹配任意一个普通字符 \W匹配任意非普通字符
[_0-9a-zA-Z] [^_0-9a-zA-Z]
In [4]: re.findall('\W+','hello_123$')
Out[4]: ['$']
In [5]: re.findall('\w+','hello_123$')
Out[5]: ['hello_123']
15. 匹配(非)空字符
元字符: \s \S
匹配规则: \s匹配任意空字符 \S匹配任意非空字符
[ \n\t\r\0]
In [6]: re.findall('\s','hello\n123\r$')
Out[6]: ['\n', '\r']
In [7]: re.findall('\S','hello\n123\r$')
Out[7]: ['h', 'e', 'l', 'l', 'o', '1', '2', '3', '$']
16. 匹配起止位置
元字符: \A \Z
匹配规则: \A匹配开始位置 \Z匹配结束位置
^ $
* 绝对匹配 一般使用在路径文件中
In [22]: re.findall('\A/\w+/\w+\Z','/home/tarena')
Out[22]: ['/home/tarena']
17. 匹配(非)单词边界位置
元字符: \b \B
匹配规则: \b匹配单词的边界 \B匹配非单词的边界
单词边界: 数字字母下划线和其他字符的交接位置为单词的边界
abc_1 haha 两个单词边界 1和空格 空格和h
In [24]: re.findall(r'\bis\b','This is a test') r是使转义字符失效
Out[24]: ['is']
匹配到是第二个is
In [25]: re.findall(r'\Bis\b','This is a test')
Out[25]: ['is']
匹配到的是单词This里面的is
元字符总结:
匹配单个字符: 普通字符 . \d \D \w \W \s \S [...] [^...]
匹配重复性: * + ? {n} {m,n}
匹配某个位置: ^ $ \A \Z \b \B
其他: | () \
转义字符
正则表达式特殊符号
. * ? $ '' "" [] {} () \ ^
如果想匹配特殊符号则加转义
\"\.\" ===> "."
r ==> raw 原生字符串 不进行转义
贪婪和非贪婪
正则表达式默认的重复匹配模式: 贪婪模式
尽可能多的向后匹配
* + ? {m,n} 这四种情况下会产生贪婪模式
尽可能少的匹配内容,满足正则表达式含义即可
在以上四种情况下加 ?
正则表达式重复匹配模式变为: 非贪婪模式
正则表达式分组
使用括号() 可以为一个正则表达式建立一个子组,子组可以看做内部的整体
子组的作用:
1. 增加子组后对正则表达式整体匹配的内容没有影响
2. 子组可以改变重复元字符的重复行为
3. 子组在某些操作中可以对子组匹配内容单独提取
In [27]: re.findall('ab(cd)','abcd')
Out[27]: ['cd']
In [28]: re.findall('(ab(cd))','abcd')
Out[28]: [('abcd', 'cd')]
In [31]: re.findall('(ab(cd)*)','abcdcdcd')
Out[31]: [('abcdcdcd', 'cd')]
子组的注意事项
1. 每个正则表达式可以有多个子组,由外到内由左到右为第一第二...子组
2. 子组通常不要交叉
捕获组和非捕获组(命名组和非命名组)
子组命名格式
(?P<name>abc)
1. 很多编程接口可以直接通过名字获取子组匹配内容
2. 捕获组中的正则表达式可以通过名字重复调用
(?P=name)调用原来命名的子组
(?P<dog>ab)cdef(?P=dog) ==> abcdefab
匹配身份证
\d{17}(\d|x)
obj = compile(pattern, flags=0)
功能: 获取正则表达式对象
参数: pattern 正则表达式
flags 功能标志位,提供更丰富的匹配 默认不添加任何功能标志位
返回值: 正则表达式对象
re模块和compile对象均有的函数
obj.findall(str,pos,endpos)
功能: 通过正则表达式匹配字符串
参数: string 目标字符串
pos 目标字符串的匹配开始位置
endpos 目标字符串的匹配结束位置
返回值: 匹配到的所有内容以列表返回
例如:
import re
pattern = r'ab'
# 获取正则表达式对象
obj = re.compile(pattern)
lst = obj.findall('abcdabcabab', 6, 9)
print(lst)
* 如果正则表达式有子组则只显示子组匹配内容
obj.split(str)
功能: 按照正则表达式切割目标字符串
参数: 目标字符串
返回值: 切割后的内容
import re
pattern = r'\s+'
# 获取正则表达式对象
obj = re.compile(pattern)
# 匹配目标字符串进行切割
lst2 = obj.split('hello world hello kitty hello china')
print(lst2)
obj.sub(replaceStr, str, max)
功能: 替换正则表达式匹配到的内容
参数: replaceStr 要替换的内容
str 目标字符串
max 最多替换几处
返回值: 返回替换后的字符串(新的字符串)
import re
pattern = r'\s+'
# 获取正则表达式对象
obj = re.compile(pattern)
# 替换目标字符串中匹配到的内容
s = obj.sub('##', 'hello world hello kitty hello china', 3)
print(s)
subn(repl, str, count)
功能: 替换正则表达式匹配到的内容
参数: repl 要替换的内容
str 目标字符串
count 最多替换几处
返回值: 返回替换后的字符串和实际替换的个数 返回的是一个元组
import re
pattern = r'\s+'
# 获取正则表达式对象
obj = re.compile(pattern)
# 替换目标字符串中匹配到的内容
s = obj.subn('##', 'hello world hello kitty hello china', 3)
print(s)
obj.finditer(str)
功能: 使用正则表达式匹配目标内容
参数: 目标字符串
返回值: 迭代对象 迭代的每个内容为一个match对象
import re
# 匹配到内容返回迭代器
t = re.finditer(r'\d+', '2008年是个多事之秋,512地震,08奥运')
for i in t:
print(i.group())
re.match(pattern,string)
功能: 匹配一个字符串的开头
参数: 目标字符串
返回值: 如果匹配到返回 match obj
没有匹配到返回 None
obj = re.match('foo', 'foo, food on the table foo')
print(obj.group())
* 匹配的内容必须在开头,否则会报错
re.search(pattern,string)
功能: 匹配一个字符串
参数: 目标字符串
返回值: 如果匹配到返回 match obj
没有匹配到返回 None
* match只能匹配字符串的开头位置,search可以匹配任意位置,但是也只能匹配一处
* 通常match对象调用其属性时,往往需要try异常处理
# search匹配
obj = re.search('foo', 'fo, food on the table')
print(obj.group())
fullmatch() 和 match类型
要求目标字符串完全匹配
re模块
compile findall split sub subn finditer search match fullmatch
compile对象
findall split sub subn finditer search match fullmatch flags groupindex groups pattern
match对象 ==>finditer search match fullmatch
end endpos expand group groupdict groups lastgroup lastindex pos re regs span start string
compile对象 属性方法 (re模块没有)
flags : 标志位
groups : 子组个数
groupindex : 捕获组形成的字典
pattern : 正则表达式
obj = re.compile(r'(?P<dog>ab)cd(ef)')
print('flags:', obj.flags) # 标志位常量
print('pattern:', obj.pattern) # 正则表达式
print('groupindex:', obj.groupindex) # 捕获组字典
print('groups:', obj.groups) # 子组个数
match对象方法及属性
endpos
lastgroup
lastindex
pos
re
string
start
end
span
group(n)
功能: 获取match对象匹配的内容
参数: 默认为0,表示获取正则整体的匹配内容
如果传入大于0的正数则表示获取对应子组匹配内容
返回值: 返回匹配到的内容
groups()
功能: 得到所有子组的内容
groupdict()
功能: 得到所有捕获组匹配的内容,以字典的形式展示
obj = re.compile(r'(?P<dog>ab)cd(?P<pig>ef)')
match_obj = obj.search('abcdefdsx')
print(match_obj.pos) # 目标字符串开头位置
print(match_obj.endpos) # 目标字符串结束位置
print(match_obj.re) # 正则表达式对象
print(match_obj.string) # 目标字符串
print(match_obj.lastgroup) # 最后一组的名字
print(match_obj.lastindex) # 最后一组是第几组
print(match_obj.start()) # 匹配到内容的开始位置
print(match_obj.end()) # 匹配到内容的结束位置
print(match_obj.span()) # 匹配到内容的起止位置
print(match_obj.group()) # 匹配正则表达式整体内容
print(match_obj.group(1)) # 匹配第一个子组的内容
print(match_obj.group(2)) # 匹配第二个子组的内容
print(match_obj.groups()) # 匹配所有子组的内容
print(match_obj.groupdict()) # 匹配捕获组所有的内容,以字典的形式展示
练习:
读取一个文件的内容,将文件中所有的以大写字母开头的单词匹配出来
import re
try:
with open('Futureisnow.txt', 'r') as f:
file = f.read()
lst = re.findall('[A-Z][\'-0-9a-zA-Z]*', file)
print(lst)
except Exception:
raise
flags 参数
作用: 辅助正则表达式,丰富匹配结果
A
ASCII
S
DOTALL
U
UNICODE
I 忽略大小写
IGNORECASE
M 对元字符 ^ $起作用,可以匹配每一行的开头结尾位置
MULTILINE
X
L
LOCALE
Scanner
T
TEMPLATE
VERBOSE
更多regester学习
https://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html