import re
一、正则表达式:记录文本规则的代码
字符串处理工具
注意:需要导入re模块
1.2特点:
语法比较复杂,可读性较差
通用性强,适用于多种编程语言
步骤:
1.导入re模块
2.使用match方法进行匹配操作
re.match()能匹配出以xxx开头的字符串
re.match(pattern,string)
pattern : 匹配的正则表达式
string : 要匹配的字符串
res = re.match("M","Milk可以成功")
print(res)
如果起始位置没有匹配成功,返回None
3.如果上一步数据匹配成功,使用group()提取数据
print(res.group())
注意:match是从开始位置匹配,匹配不到就没有,且匹配的是表达式整体
二、匹配单个字符
字符 功能
. 匹配任意一个字符(除了\n)
\[\] 匹配\[\]中列举的字符
\d 匹配数字,即0~9
\D 匹配非数字,即不是数字
\s 匹配空白,即空格,tab键
\S 匹配非空白
\w 匹配单词字符,即a-z,A-Z,0-9,_
\W 匹配非单词字符
1. . 匹配任意一个字符(除了\n) --常用
res = re.match('.','hello')
print(res)
print(res.group())
2. [] 匹配[]中列举的字符 --常用
res = re.match('[he]','eello') #中括号中有,就能匹配成功
res = re.match('[12345]','5432')
res = re.match('[1-5]','3412')
匹配0-9的第一种写法
res = re.match('[0123456789]','5432')
匹配0-9的第二种写法
res = re.match('[0-9]','3412')
没有3
res = re.match('[0-24-9]','3412') # 0-2,4-9
res = re.match('[a-zA-Z].','Hello') #a-zA-Z代表列举出所有大小写字母
print(res)
print(res.group())
3. \d 匹配数字,即0~9 --常用
res = re.match('\d','2345')
print(res)
print(res.group())
4. \D 匹配非数字,即不是数字 --常用
res = re.match('\D','s2345') #只要不是数字都能够匹配
print(res)
print(res.group())
5. \s 匹配空白,即空格,tab键 --常用
res = re.match('\s.h',' hh')
print(res)
print(res.group())
# 6. \S 匹配非空白
res = re.match('\S','hh')
print(res)
print(res.group())
7. \w 匹配单词字符,即a-z,A-Z,0-9,_,汉字
res = re.match('\w','景hh')
print(res)
print(res.group())
8. \W 匹配非单词字符
res = re.match('\W','.')
print(res)
print(res.group())
三、匹配多个字符
字符 功能
* 匹配前一个字符出现0次或者无限次,即可有可无
+ 匹配前一个字符出现1次或者无限次,即至少有一次
? 匹配前一个字符出现1次或者0次,即要么有一次,要么没有
{m} 匹配前一个字符出现每次
{m,n} 匹配前一个字符出现m到n次
1. * 匹配前一个字符出现0次或者无限次,即可有可无
res = re.match('\w*','hello') # *相当于修饰\w #hello
# res = re.match('\w*','hello。') #hello
# res = re.match('\d*','hello。') #没有匹配出数字,啥也没有,不会有任何输出,出现0次
print(res.group())
2. + 匹配前一个字符出现1次或者无限次,即至少有一次
res = re.match('\d+','我很开心')
print(res.group()) #报错,没有匹配到数字,+修饰时至少有一次
res = re.match('\d+','1我很开心')
print(res.group())
3. ? 匹配前一个字符出现1次或者0次,即要么有一次,要么没有
res = re.match('\d?','12我很开心')
print(res.group()) # 最多只匹配一次,只输出1
4. {m} 匹配前一个字符出现每次
res = re.match('\w{3}','python')
print(res.group()) #pyt
5. {m,n} 匹配前一个字符出现m到n次
注意:必须符合m<n的条件
res = re.match('\w{2,9}','python')
print(res.group()) #pyt
当n小于等于要匹配内容的长度时,匹配n个长度,当大于时匹配内容长度个字符,当n超过要匹配内容的长度,发生报错
四、匹配开头和结尾
字符 功能
^ 匹配字符串开头
$ 匹配字符串结尾
1. ^ 表示以...开头;表示对...取反
res = re.match('^py','python')
print(res.group())
注意:^ 在[]中表示不匹配
res = re.match('[^py]','thon') #[^py]表示匹配除了p、y之外的字符
print(res.group()) #匹配到了t
2. $ 匹配字符串结尾
res = re.match('.{3}\w$','thon')
print(res.group())
五、匹配分组
字符 功能
| 匹配左右任意一个表达式
(ab) 将括号中字符作为一个分组
\num 引用分组num匹配到的字符串
(?P<name>) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串
1. | 匹配左右任意一个表达式
res = re.match("abc|def",'abc')
print(res.group())
re = re.match(".|\d","abc")
print(re.group())
2. (ab) 将括号中字符作为一个分组
res = re.match("(\d*@qq.com)",'94567@qq.com')
print(res.group())
3. \num 引用分组num匹配到的字符串 --经常在匹配标签时使用
res = re.match("<\w*>\w*</\w*>","<html>login</html>")
res = re.match("<(\w*)>\w*</\\1>","<html>login</html>")
res = re.match(r"<(\w*)><(\w*)>.*</\2></\1>","<html><body>login</body></html>")
# 注意:从外到内排序,编号从1开始
print(res.group())
4. (?P<name>) 分组起别名
5. (?P=name) 引用别名为name分组匹配到的字符串
res = re.match(r"<(?P<L1>\w*)><(?P<L2>\w*)>.*</(?P=L2)></(?P=L1)>","<html><body>login</body></html>")
print(res.group())
六、应用:匹配网址
前缀一般是www, 后缀: .com、.cn、 .org
li = ['www.baidu.com','www.python.org','http.jd.cn','www.py.en','www.abc.com']
res = re.match(r'www(\.)\w*\1(com|org|cn)','www.baidu.com')
print(res.group())
li = ['www.baidu.com','www.python.org','http.jd.cn','www.py.en','www.abc.com']
for i in li:
res = re.match(r'www(\.)\w*\1(com|org|cn)',i)
if res:
print(res.group())
else:
print(f'{i}这个网址有问题')
七、高级用法
1. search(): 扫描整个字符串并返回第一个成功匹配到的自符串,如果匹配失败,则返回None
res = re.search("th","1python2python")
print(res.group())
2. findall(): 将列表形式返回整个字符串中所有匹配到的自符串
res = re.findall("\d","1python2python")
print(res) #findall()方法不需要用group()方法
print(type(res))
总结: match()从头开始匹配,匹配成功返回match()对象,匹配失败就返回None,通过group()进行提取,只匹配一次
search():从头到尾匹配,匹配成功返回第一个匹配成功的对象,匹配失败就返回None,通过group()进行提取,只匹配一次
findall():从头到尾匹配,匹配成功返回一个列表,匹配所有匹配成功的数据,不需要通过group()进行提取,没有group()方法
- sub(): 将匹配到的数据进行替换
re.sub(pattern,repl,string,count)
参数
pattern: 正则表达式(代表需要被替换的,也就是字符串里面的旧内容
repl: 新内容
string: 字符串
count: 指定要替换的次数
res = re.sub("python","Mike","1python2alice3python",1)
print(res)
res = re.sub("\d","1","这是这个月的第29天",1)
print(res)
- split(): 根据匹配进行切割字符串,并返回一个列表
re.split(pattern,string,maxsplit)
参数
pattern: 正则表达式
repl: 新内容
maxsplit: 表示最大分割次数
res = re.split(",","hello,world,hhh,lll,123",2) #没有设置最大分割次数就全部分割
print(res)
八、贪婪与非贪婪
贪婪匹配(默认):在满足匹配时,匹配尽可能长的自符串,默认情况下,采用贪婪匹配
res = re.match("em*","emmmm...")
print(res.group()) #emmmm
非贪婪匹配:在满足匹配的时候,匹配尽可能短的字符串,使用?来表示非贪婪算法
res = re.match("em*?","emmmm...")
print(res.group()) #e
res = re.match("m*?","mmmm...")
print(res.group()) #啥也没有
res = re.match("m{1,5}?","mmmmm...")
print(res.group()) #m
八、原生字符串
python中字符串前面加上r表示原生字符串
print("sixs\tar") #sixs ar
print("sixs\\tar") #sixs\tar
print(r"sixs\tar") #sixs\tar
res = re.match("\\\\","\game")
# 正则表达式中,匹配字符串中的字符\需要\\\\,加入原生字符串,\\代表\
print(res.group())