文章内容是看完b站教程:Python编程:正则表达式的笔记,部分内容摘自Python 正则表达式
1 特殊字符罗列
学习正则表达式,首先一定要清楚各类正则表达式符号的含义。
.:表示匹配除了换行符之外的任何单个字符
*:表示匹配前面的子表达式任意次,包括0次
+:表示匹配前面的子表达式一次或多次,不包括0次
?:表示匹配前面的子表达式0次或1次
\:转义
[]:表示要匹配某几种类型的字符
^:开始位置
$:结束位置
{
}:表示前面的字符匹配指定的次数
|:或
():组选择
匹配某种字符类型
\d 匹配0-9之间任意一个数字字符,等价于表达式[0-9]
\D 匹配任意一个不是0-9之间的数字字符,等价于表达式[^0-9]
\s匹配任意一个空白字符,包括空格、tab、换行符等,等价于表达式[\t\n\r\f\v]
\S匹配任意一个非空白字符,等价于表达式[^\t\n\r\f\v]
\w匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式[a-zA-Z0-9_]
缺省情况也包括Unicode文字字符,如果指定ASCII码标记,则只包括ASCII字母
source='''
王亚辉
tony
刘文武
'''
import re
p=re.compile(r'\w{2,4}')#全匹配
p=re.compile(r'\w{2,4}',re.A)#只匹配'tony'
print(p.findall(source))
\W匹配任意一个非文字字符,等价于表达式[^a-zA-Z0-9_]
反斜杠也可以用在方括号里面,比如[\s,.]表示匹配:任何空白字符,或者逗号,或者点
下面对各个特殊字符一一说明。
特殊字符1 .:表示匹配除了换行符之外的任何单个字符
content='''苹果是绿色的
橙子是橙色的
香蕉是黄色的
乌鸦是黑色的'''
import re
p=re.compile(r'.色')# r的含义是纯文本,忽略转义 # compile返回一个pattern类,可用各种常见方法处理
for one in p.findall(content):# findall返回list,list里的元素是字符串
print(one)
运行结果为
绿色
橙色
黄色
黑色
特殊字符2 *:表示匹配前面的子表达式任意次,包括0次
content='''苹果,是绿色的
橙子,是橙色的
香蕉,是黄色的
乌鸦,是黑色的'''
正则表达式
,.*
代表匹配逗号后面的所有字符。content的匹配结果为
,是绿色的
,是橙色的
,是黄色的
,是黑色的
特殊字符3 +:表示匹配前面的子表达式一次或多次,不包括0次
.+和.*类似,不同的是+匹配至少1次,而*可以匹配0次
特殊字符4 {}:匹配连续多次
表达式 油{3,4}表示匹配连续的油字至少3次,至多4次
\d{11}提取连续11个数字,如手机号是11位的
特殊字符5 \:转义元字符
比如要在下面的文本中搜索 所有点前面的字符串,也包括点本身
苹果.是绿色的
橙子.是橙色的
香蕉.是黄色的
因为要搜索的内容本身就包含元字符,可以使用反斜杠进行转义,使用.*\.
即可
特殊字符6 []:匹配里面任意一个字符
[abc]可以匹配abc里面的任意一个字符。等价于[a-c]
[a-c]中间-表示一个范围从a到c
一些元字符在方括号内就是普通字符,如[akm.]匹配a k m .里面任意一个字符
特殊字符7 ^:起始位置
如果在方括号里使用^,表示非方括号里面的字符集合
^表示匹配文本的起始位置。
正则表达式可以设定单行模式和多行模式
如果是单行模式,表示匹配整个文本的开头位置
如果是多行模式,表示匹配文本每行的开头位置。
python代码缺省是单行模式,如果设置多行模式
content='''001-苹果价格-60
002-橙子价格-70
003-香蕉价格-80
'''
import re
p=re.compile(r'^\d+',re.M)#re.M表示设置多行模式
for one in p.findall(content):
print(one)
运行结果
001
002
003
特殊字符8 $:结束位置
一样有单行模式和多行模式
特殊字符9 ():组选择
content='''苹果,苹果是绿色的
橙子,橙子是橙色的
香蕉,香蕉是黄色的
'''
import re
p=re.compile(r'^(.*),',re.M)
for one in p.findall(content):
print(one)
"""最后结果
苹果
橙子
香蕉
"""
content='''张三,手机号码18350505050
张四,手机号码18350505051
张五,手机号码18350505052
'''
import re
p=re.compile(r'^(.+),.+(\d{11})',re.M)
for one in p.findall(content):
print(one)
"""最后结果
('张三','18350505050')
('张四','18350505051')
('张五','18350505052')
"""
特殊字符10 ?:表示匹配前面的子表达式0次或1次
等价于{0,1}
2 re包方法
re是有关正则表达式的包。上面讲解主要用到了recompile和findall方法。
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None
re.search匹配整个字符串,直到找到一个匹配。
match 和 search 是匹配一次,findall 匹配所有。
详细使用可以另查资料,下文只简略带过。
2.1 re.match(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
正则表达式可选标志:
- re.I 使匹配对大小写不敏感
- re.L 做本地化识别(locale-aware)匹配
- re.M 多行匹配,影响 ^ 和 $
- re.S 使 . 匹配包括换行在内的所有字符
- re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
- re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None
2.2 re.search(pattern, string, flags=0)
re.search匹配整个字符串,直到找到一个匹配。
2.3 findall(string[, pos[, endpos]])
match 和 search 是匹配一次,findall 匹配所有。
import re
pattern = re.compile(r'\d+') # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)
print(result2)
'''输出结果
['123', '456']
['88', '12']
'''
2.3 re.compile(pattern[, flags])
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
参数:
- pattern : 一个字符串形式的正则表达式
- flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
- re.I 忽略大小写
- re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
- re.M 多行模式
- re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
- re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
- re.X 为了增加可读性,忽略空格和 # 后面的注释
content='''张三,手机号码18350505050
张四,手机号码18350505051
张五,手机号码18350505052
'''
import re
p=re.compile(r'^(.+),.+(\d{11})',re.M)
for one in p.findall(content):
print(one)
"""最后结果
('张三','18350505050')
('张四','18350505051')
('张五','18350505052')
"""
2.4 re.split
Import re
names='关羽;张飞,赵云, 马超,黄忠 李逵'
# 以下正则表达式指定了,分隔符为分号、逗号、空格里面的任意一种,并且该符号周围可以有不定数量的空格
namelist= re split(r'[;,\s]\s*', names)
print(namelist)
2.5 re.sub(pattern, repl, string, count=0, flags=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。(是函数的话不会用)
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
import re
phone = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python注释
num = re.sub(r'#.*$', "", phone)
print "电话号码是: ", num
# 删除非数字(-)的字符串
num = re.sub(r'\D', "", phone)
print "电话号码是 : ", num
'''结果
电话号码是: 2004-959-559
电话号码是 : 2004959559
'''
names='''
下面是这学期要学习的课程
<a href='https://www.bilibili.com/video/av66771949/?p=l'target='blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是牛顿第2运动定律
<a href='https://www.bilibili.com/video/av46349552/p=125'target='blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是毕达哥拉斯公式
<a href='https://www.bilibili.com/video/av90571967/?p=33'target='blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是切割磁力线
'''
#替换函数,参数是 Match对象
def subfunc(match):
#match对象的group(0)返回的是整个匹配上的字符串
src=match.group(0)
# Match对象的 group(1)返回的是第一个group分组的内容
number=int(match.group (1))+6
dest=f'/av{
number}/'
print(f'{
av}替换为{
dest}')
#返回值就是最终替换的字符串
return dest
newstr= re.sub(r'/av(\d+?)/', subfunc, names)
print(newStr)
贪婪的特殊字符,“*”,“+”,"?"
‘*’,’+’,’?'都是贪婪的,使用时会尽可能多的匹配内容
source='<html><head><title>Title</title>'
import re
p=re.compile(r'<.*>')
print(p)
结果是
['<html><head><title>Title</title>']
因为开头的<
和结尾的>
匹配上了。要向匹配所有的标签,就要使用非贪婪模式,也就是在星号后面加上?
,变成<.*?>
练习
匹配13或15开头的电话号码,1[35]\d{9}
匹配13、14、15、16开头的电话号码,1[3-6]\d{9}