1.正则基础
2.高级用法
3.贪婪与非贪婪
4.原生字符串
#### 匹配单个字符
| 字符 | 功能 |
| :--: | :------------------------------- |
| . | 匹配任意1个字符(除了\n) |
| [ ] | 匹配[ ]中列举的字符 |
| \d | 匹配数字,即0-9 |
| \D | 匹配非数字,即不是数字 |
| \s | 匹配空白,即 空格,tab键 |
| \S | 匹配非空白 |
| \w | 匹配单词字符,即a-z、A-Z、0-9、_ |
| \W | 匹配非单词字符 |
#### 匹配多个字符
| * | 匹配前一个字符出现0次或者无限次,即可有可无 |
| ----- | --------------------------------------------------- |
| + | 匹配前一个字符出现1次或者无限次,即至少有1次 |
| ? | 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
| {m} | 匹配前一个字符出现m次 |
| {m,n} | 匹配前一个字符至少m个,最多n个, m <= n |
#### 匹配开头结尾
| ^ | 匹配字符串开头 |
| ---- | -------------- |
| $ | 匹配字符串结尾 |
#### 匹配分组
| \| | 匹配左右任意一个表达式 |
| ------------ | -------------------------------- |
| (ab) | 将括号中字符作为一个分组 |
| `\num` | 引用分组num匹配到的字符串 |
| `(?P<name>)` | 分组起别名 |
| (?P=name) | 引用别名为name分组匹配到的字符串 |
```python
. 匹配除换行符以外的任意字符
[0123456789] []是字符集合,表示匹配方括号中所包含的任意一个字符
[sunck] 匹配's','u','n','c','k'中任意一个字符
[a-z] 匹配任意小写字母
[A-Z] 匹配任意大写字母
[0-9] 匹配任意数字,类似[0123456789]
[0-9a-zA-Z] 匹配任意的数字和字母(注意之间没有空格)
[0-9a-zA-Z_] 匹配任意的数字、字母、下划线(注意之间没有空格)
[^sunck] 匹配除了sunck这几个字母以外的所有字符
^称为脱字符,表示不匹配集合中的字符
[^0-9] 匹配所有的非数字字符
\d 匹配数字,效果[0-9]
\D 匹配非数字字符,效果同[^0-9]
\w 匹配数字,字母和下划线,效果同[0-9a-zA-Z_]
\W 匹配非数字,字母和下划线,效果同[^0-9a-zA-Z_]
\s 匹配任意的空白符(格,换行,回车,换页,制表),效果同
[ \f\n\r\t]
\S 匹配任意的非空白符,效果同[^ \f\n\r\t]
下方的x,y,z,n均为假设的普通字符,不是正则表达式的元字符
(xyz) 匹配小括号内的xyz(作为一个整体去匹配)
x? 匹配0个或者任意1个x
x* 匹配0个或者任意多个x(.*表示匹配0个或者任意多个字符(换行符除外))
x+ 匹配至少一个x
x{n} 匹配确定的n个x(n是一个非负整数)
x{n,} 匹配至少n个x
x{n,m}匹配至少n个最多m个。注意:n <= m
x|y |表示或,匹配的是x或y
# 1.正则表达式是一个特殊的字符序列
# 2.match方法:从字符串的开始位置匹配正则表达式,返回match对象
# 匹配到数据之后,需要使用group方法来提取数据
import re # 导入re模块
# re.match(正则表达式, 要匹配的字符串)
# res = re.match('jiu', 'jiuge')
# print(res.group())
# 3.匹配单个字符
# . 匹配任意一个字符,除\n之外
# res = re.match('.', 'jiuge')
# res = re.match('ji..', 'ji哈ge')
# print(res.group())
# [] :匹配[ ]中列举的字符
# res = re.match('[0123456789]', '8Hello')
# res = re.match('[0-9]', '2Hello')
# res = re.match('\d', '23Hello')
# res = re.match('[0-35-9]', '3Hello') # 0123, 56789
# \D:匹配非数字
# res = re.match('\D\D', ' Hello')
# \s:匹配空白
# res = re.match('\sHe', ' Hello')
# \w:匹配单词字符 a-z,A-Z,0-9,_
# res = re.match('\w', 'sixstar')
# \W:匹配非单词字符
# res = re.match('\W', '%&@')
# print(res.group())
# 4.匹配多个字符
# * : 匹配前一个字符出现0次或者无限次,即可有可无
# res = re.match('\D*', 'hello%%$2345')
# res = re.match('[A-Z]*[a-z]*', 'SSixstar')
# + : 匹配前一个字符出现1次或者无限次,即至少有1次
# 要求:名字开头没有数字
name = ['jiuge', '2jiuge', 'jg', '_jiuge']
for i in name:
res = re.match('[a-zA-Z_]{1,3}', i)
# print(res.group())
if res:
print('正确的名字:', res.group())
else:
print('不正确的:', i)
# ?:匹配前一个字符出现1次或者0次,即要么有1次,要么没有
# res = re.match('[a-z]?\d', '6789')
# print(res.group())
# {m} : 匹配前一个字符出现m次
# res = re.match('[a-z0-9]{6}', '1w324ebvs4') # m=6
# {m, n}:匹配前一个字符出现从m到n次, 最少是m次,最多是n次
# res = re.match('[a-z0-9]{3,6}', 'abcdejksgk') # m=3, n=6
# print(res.group())
import re
# 1. ^ 匹配字符串开头
# 1>以什么开头
# res = re.match('^ab', 'abcd')
# res = re.match('^[0-9]', '123abcd')
# 2>对什么取反, ^放在[]中
# res = re.match('[^0-9]', 'abcd') # [^0-9]匹配非数字的字符
# print(res.group())
# 总结:
# 'abc' 表示字符串中开头有abc就匹配成功
# '[abc]' 表示字符串中有'a'或'b'或'c'就匹配成功
# '^abc'表示以abc开头就匹配成功
# '[^abc]' 表示匹配除'a','b','c'之外的字符
# 2. $ 匹配字符串结尾
# res = re.match('\w*\d$', 'jiuge4')
# print(res.group())
elist = ['jiuge@qq.com', 'jiu@qq.com', 'com.jiuge@qq.com', 'jiuge@163.com']
for i in elist:
# res = re.match('[a-z]{5}.[a-z]+.[a-z]+', i)
# 或:
res = re.match('^jiuge.qq.com$', i)
if res:
print('匹配成功:', res.group())
else:
print('匹配失败:', i)
import re
# (ab) 将括号中字符作为一个分组
# res = re.match('\w{5}@(qq|163|129).com', 'jiuge@163.com')
# print(res.group())
# \num 引用分组num匹配到的字符串
# res = re.match(r'<(\w*)>\w*</\1>', '<html>hhh</html>')
# res = re.match(r'<(\w*)><(\w*)>.*</\2></\1>', '<html><h1>hhh</h1></html>')
# print(res.group())
# (?P<name>) 分组别名
res = re.match(r'<(?P<n1>\w*)><(?P<n2>\w*)>.*</(?P=n2)></(?P=n1)>', '<html><h1>hhh</h1></html>')
print(res.group())
# 1.search()会扫描整个字符串并返回第一个成功的匹配
# res = re.search('\d.', '读到了第45页, 明天读54页')
# print(res.group())
# match方法从开始位置匹配,search扫描整个字符串进行匹配
# 2.findall()以列表形式返回匹配到的字符串
# res = re.findall('\d', '读到了第45页, 明天读54页')
# res2 = re.findall('\d{2}', '读到了第45页, 明天读54页')
# res = re.findall('\d', 'a=1,b=2,c=3')
# print(res)
# print(res2)
# 总结:
# match: 从头开始匹配 匹配一次 不常用
# search: 从头到尾匹配 匹配一次 较常用 (仅返回第一个匹配成功的数据)
# findall: 从头到尾匹配 匹配所有 最常用
# 3.sub() 将匹配到的数据进行替换
# re.sub(需要被替换的正则表达式,表示用什么来替换,字符串,替换的次数count)
# res = re.search('\d', '读到了第45页')
# print(res.group())
# res = re.sub('\d', '8', '读到了第450页', 1) # 只替换第一个,如果去掉‘1’,则是全部替换
# print(res)
# res = re.sub('\D', '20', '这是什么88啊')
# print(res)
# 4.split()根据匹配进行切割字符串,并返回一个列表
# res = re.split('[@:]', 'a@b:c@12') # 左边的是以什么来分割
# res = re.split(':|@', 'a@b:c@12')
# print(res)
# 5.贪婪与非贪婪
# 贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配.
# 非贪婪匹配:在满足匹配时,匹配尽可能短的字符串,使用?来表示非贪婪匹配
# res = re.search('ab*', 'abbbc')
# * 要么0次要么无限次, ?要么0次要么1次
# 在*、+、{m,n} 后面加上?, 表示使贪婪变成非贪婪
# res = re.search('ab*?', 'abbbc')
# 加了一个?表示非贪婪匹配,尽可能少的。?修饰的是前面的*, *最少的是取0个值
# b的0个就是空字符串
# print(res.group())
# res = re.match('a*', 'aaaa')
# res = re.match('a*?', 'aaaa')
# print(res)
# print(res.group())
# st = 'ab1234cd'
# res = re.match('ab(\d+)', st) # ab1234
# res = re.match('ab(\d+?)', st) # ab1
# print(res.group())
# 6.原生字符串
# python中字符串前面加上 r 表示原生字符串
# print('12\\n3')
# print('12\n3')
# 如果需要匹配数据中的\, 正则表达式中需要四个\
# res = re.match('\\\\', '\def')
# 因为在正则表达式中,\\就是一个反斜杠
# res = re.match(r'\W', '\def')
# res = re.match(r'\\\\', r'\\def')
# print(res.group())
# st = 'c:\\a\\b\\d'
# # print(st)
#
# res = re.match(r'c:\\a', st)
#
# print(res.group())