目录
正则表达式语法规则
百度百科简介:正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。
字符
字符 | |
---|---|
. | 匹配一个任意字符,换行符除外 |
\ | 转义字符,把带有特殊含义的字符转换成无意义字符 |
[...] | 字符集,匹配其中的任意一位。a[012]b,可以匹配a0b,a1b,a2b;可以指定范围,a[0-9]b;a[0-9a-zA-Z] |
^ | 取反,需要放在[]里面的最前面,a[^0-9]b 表示匹配一个非数字的任意字符 如果要匹配数字或者^字符,a[0-9^]b或者写成a[\^0-9]b |
预定义字符集
\d | 匹配数字,等同于[0-9] |
\D | 匹配非数字,等同于[^0-9] |
\s | 匹配空白字符,等同于[\n\t\r\f\v] ,换行、空格、\f换页符,\v 垂直制表符 |
\S | 匹配非空白字符 |
\w | 匹配单词字符(数字、字母、下划线),等同于[0-9a-zA-Z_] |
\W | 匹配非单词字符 |
数量词
* | 匹配前一个字符0或者无限次 |
+ | 匹配前一个字符1或者无限次 |
? | 匹配前一个字符0次或者1次,一般和括号()组合使用 |
{M} | 匹配前一个字符M次,{N,M}匹配N-M次,{M,} 最少M次,无上限 |
贪婪和非贪婪
贪婪:再整个表达式匹配成功的前提下,尽可能多的匹配
非贪婪:在整个表达式匹配成功的前提下,尽可能少的匹配
贪婪 | .*或者\s* 贪婪匹配,会一直匹配到最后不能匹配的位置 |
非贪婪 | .*? 非贪婪匹配,会匹配每一次出现的结果 |
例:<p>123</p><p>abcde</p> ,使用贪婪和非贪婪模式匹配这个字符串。
<p>.*</p> 贪婪匹配,*号会匹配到尽可能多的东西,匹配整个123</p><p>abcde,最后匹配结果只有一个结果集,就是整个字符串。
<p>.*?</p> 非贪婪匹配,会匹配每一次出现的结果。匹配的结果有两个:<p>123</p>和<p>abcde</p>。
边界匹配(不消耗匹配字符串中的字符)
^ | 匹配字符串的开头 |
$ | 匹配字符串的结尾,空格回车也会参与匹配 |
\A | 字符串的开头(Python中独有的写法) |
\Z | 字符串的结尾(Python中独有的写法) |
\b | 匹配单词和非单词的边界,单词和非单词的交界。(单词字符包括数字、字母、下划线、汉字) tom,do you have time tomorrow 匹配tom人名,tom\b tomorrow tom后面o是单词,不满足\b的要求 |
\B | 匹配要么都是单词,要么都是非单词 |
逻辑、分组
| | 左右表达式任意匹配一个。尝试先匹配左边再匹配右边。经常和括号配合使用,hello (aaa|bbb) |
( ) | 括号代表分组,或者一个整体。 |
\num | 引用第num个分组 分组示例: Anni like Anni John like Jerry \1代表引用第一个分组的值,做搜索。 意思是把like前面的字符串用到后面\1的地方,a like b,其中b的值是和a一样的, 结果是检索出 Anni like Anni |
正则练习
在线练习正则表达式的网址: http://tool.oschina.net/regex/
1、用正则匹配如下网址
http://www.baidu.com
https://www.sina.com.cn
https://www.baidu.com/s?wd=python&name=anni
ftp://www.antvv.com
https://www.antvv.com?cate=3
(http|https|ftp)://www\.\w+\.(com\.cn|com|cn|net|gov)(/\w+)*(\?\w+=\w+)?
2、电话号码匹配(11位)
+86 13456789012
18999245678
12341134
(\B(\+86 )?|\b)1[3-9]\d{9}
3、身份证 (18位,最后一位可能是X)
368756483729876657
36875648372987665X
3687564837298766571
3687564837298766573X
\b\d{17}(\d|X)\b
4、匹配年份1990-2019
1990
2019
1989
2020
2010
20101
22010
\b(199|20(0|1))\d\b
Python re模块介绍
引入模块
import re
reg=re.compile('正则') 编译正则表达式,之后就可以通过该对象匹配
正则检索
result=reg.match() 从文本中匹配正则表达式,从字符串第一个位置开始匹配,只匹配一次,匹配到了就返回match对象,否则返回None。
result.group() 从匹配到的对象中取出分组,如果有分组则传入分组编号取出相应组的返回值,如果没有分组不需要传或者传0。
#-*- coding: UTF-8 -*-
import re
# 取出手机号前三位和后四位
phone="13123456789"
phone_reg=re.compile("(1[3-9]\d)(\d{4})(\d{4})")
result=phone_reg.match(phone)
print(result.group(1))
print(result.group(3))
# 打印结果
# 131
# 6789
正则表达式:(1[3-9]\d)(\d{4})(\d{4}),把手机号分成了三组,每个()是一个分组,如果取第一分组就用group(1)。
如果不取分组的信息,取整个正则匹配的数据,则group不需要传参数,或者group(0)。
#-*- coding: UTF-8 -*-
import re
phone="13123456789"
phone_reg=re.compile("(1[3-9]\d)(\d{4})(\d{4})")
result=phone_reg.match(phone)
print(result.group())
print(result.group(0))
# 打印结果:
# 13123456789
# 13123456789
reg.search() 从字符串的任意位置开始搜索,match的升级版,只匹配一次。
如果上个例子中,把手机号改掉,让 phone="我的手机号是13123456789",用match函数是无法检索出来的。
#-*- coding: UTF-8 -*-
import re
phone="我的手机号是13123456789"
phone_reg=re.compile("(1[3-9]\d)(\d{4})(\d{4})")
result=phone_reg.match(phone)
print(result)
# 打印结果
# None
改成用search就可以了
#-*- coding: UTF-8 -*-
import re
phone="我的手机号是13123456789"
phone_reg=re.compile("(1[3-9]\d)(\d{4})(\d{4})")
result=phone_reg.search(phone)
print(result.group())
# 打印结果
# 13123456789
reg.findall() 任意位置搜索,匹配多次。匹配所有满足条件的字符。
返回的是列表,如果正则里面有分组,返回元组形式包装的分组返回信息;
如果没有分组,列表里面直接是返回值。
在分组开始的括号后面加上?:代表该括号不作为一个分组
str='''
我的名字是王小明,我的手机号是13114567890,我的身份证号是330721197010040515。
我的名字是孙其绥,我的手机号是13114567890,我的身份证号是330702197108020812。
我的名字是孙群领,我的手机号是13114567890,我的身份证号是33072419770516031X。
'''
如何检索出上面str的所有手机号码呢?
#-*- coding: UTF-8 -*-
import re
str='''
我的名字是王小明,我的手机号是13114567890,我的身份证号是330721197010040515。
我的名字是孙其绥,我的手机号是13114567890,我的身份证号是330702197108020812。
我的名字是孙群领,我的手机号是13114567890,我的身份证号是33072419770516031X。
'''
phone_reg = re.compile("手机号是(1[3-9]\d{9}),我的")
result = phone_reg.findall(str)
print(result)
# 打印结果
# ['13114567890', '13114567890', '13114567890']
现在可以检索出手机号码了,那么思考下,怎么检索出每个号码的前3位和后四位呢?结合上面的例子思考3秒钟。
#-*- coding: UTF-8 -*-
import re
str='''
我的名字是王小明,我的手机号是13114567890,我的身份证号是330721197010040515。
我的名字是孙其绥,我的手机号是13114567890,我的身份证号是330702197108020812。
我的名字是孙群领,我的手机号是13114567890,我的身份证号是33072419770516031X。
'''
# 使用分组,如果不想让中间四位检索出来,就加?:使第二个不作为一个分组
phone_reg = re.compile("手机号是(1[3-9]\d)(?:\d{4})(\d{4}),我的")
result = phone_reg.findall(str)
print(result)
# 打印结果
# [('131', '7890'), ('131', '7890'), ('131', '7890')]
reg.finditer() 匹配所有满足条件的,返回一个可迭代对象
遍历返回的是match对象,用group获取值
#-*- coding: UTF-8 -*-
import re
str='''
我的名字是王小明,我的手机号是13114567890,我的身份证号是330721197010040515。
我的名字是孙其绥,我的手机号是13114567890,我的身份证号是330702197108020812。
我的名字是孙群领,我的手机号是13114567890,我的身份证号是33072419770516031X。
'''
phone_reg = re.compile("手机号是(1[3-9]\d)(?:\d{4})(\d{4}),我的")
result = phone_reg.finditer(str)
for once in result:
print(once.group(1)+"***"+once.group(2))
# 打印结果
# 131***7890
# 131***7890
# 131***7890
正则分割字符串
split() 通过正则表达式分割字符串,结果返回一个list。
#-*- coding: UTF-8 -*-
import re
str2="唱_跳,rap_篮球"
# 同时用多种字符进行分割
regex_sp = re.compile(",|_")
result = regex_sp.split(str2)
print(result)
# 返回结果
# ['唱', '跳', 'rap', '篮球']
字符串替换
sub("替换字符",目标str,替换次数) 字符串替换,替换次数不设置的话,默认替换所有。
bad_str_reg = re.compile("[><\?\"/\|\\\\:\*]")
bad_str_reg.sub("目标字符",str)
subn() 字符串替换后返回替换次数和替换过的字符串
用re去调用的话:
re.sub(正则表达式,"替换字符",目标str,替换次数)
#-*- coding: UTF-8 -*-
import re
filename = "/清\华|大<学:校*花>校?花\"名.jpg"
result = re.sub("[><\?\"/\|\\\\:\*]","",filename)
print(result)
result2 = re.sub("[><\?\"/\|\\\\:\*]","",filename,5)
print(result2)
result3 = re.subn("[><\?\"/\|\\\\:\*]","",filename)
print(result3)
# 打印结果
# 清华大学校花校花名.jpg
# 清华大学校*花>校?花"名.jpg
# ('清华大学校花校花名.jpg', 9)
分组引用
\num 引用分组
#-*- coding: UTF-8 -*-
import re
phone_num="13114567890"
phone_reg=re.compile("(1[3-9]\d)(\d{4})(\d{4})")
result=phone_reg.sub("\\1****\\3",phone_num)
# 第一分组+****+第三分组
print(result)
# 打印结果
# 131****7890
匹配中文
如何获取一段字符串中的所有中文内容。
[\u4e00-\u9fa5]
或者
[一-龥]
(从第一个中文“一”匹配到最后一个中文“龥”(yù))
#-*- coding: UTF-8 -*-
import re
str3="我的名字是王小明,我的手机号是13114567890,我的身份证号是330721197010040515。"
print(re.findall("[\u4e00-\u9fa5]+",str3))
print(re.findall("[一-龥]+",str3))
# 打印结果
# ['我的名字是王小明', '我的手机号是', '我的身份证号是']
# ['我的名字是王小明', '我的手机号是', '我的身份证号是']