正则表达式(一)
应用场景
- 数据验证:检查字符串是否符合特定的格式,如电子邮件地址、电话号码、URL、IP地址、日期格式等。
- 数据抽取:从文本中提取所需的信息,如提取日志文件中的日期、错误代码或者提取网页中的链接。
- 文本替换:在文本编辑器中进行查找和替换操作,或者在编程中对字符串进行复杂的替换,如大小写转换、删除多余空格等。
- 文本分割:使用复杂的分隔符或模式对字符串进行分割,得到字符串数组。
- 字符串解析:解析复杂格式的字符串,如解析自定义的配置文件内容。
- 语法高亮:在编程开发环境中,对代码进行语法高亮显示。
- 自然语言处理:在自然语言文本中识别句子、单词、短语的模式,如词干提取、词性标注等。
- Web爬虫:从网页源码中提取所需的数据,如图片链接、特定的文本信息等。
- 文件重命名:在文件管理中,对大批量文件进行基于模式的重命名操作。
- 日志分析:提取、分析服务器日志文件中的关键信息,以便进行故障排除、性能监控等。
使用原则
- 简单化:尽可能使用简单的表达式。复杂的表达式可能难以理解和维护,并且可能导致性能问题。
- 明确性:你的正则表达式应该明确无误地匹配你想要的文本,不应该匹配到错误的文本。
- 避免过度使用:对于一些简单的字符串操作,如简单的查找、替换或分割,使用基本的字符串函数会更高效。
- 避免贪婪匹配:默认情况下,正则表达式的量词(如
*
和+
)是贪婪的,它们会尽可能多地匹配字符。在许多情况下,使用非贪婪量词(如*?
和+?
)可以提高效率并防止意外匹配。 - 重用模式:编译常用的正则表达式,使用
re.compile()
函数。这样可以提升性能,因为编译后的模式可以重复使用。 - 注释和文档化:复杂的正则表达式应该有注释说明每个部分的功能,使得其他开发者(或未来的你)可以理解它的工作原理。
- 测试:对正则表达式进行彻底测试,确保它们在各种情况下都按预期工作,并处理好边缘情况。
- 考虑可读性:尽管正则表达式可能非常强大,但它们也可以变得难以读懂。尽量写出易于理解的表达式,或将复杂的表达式分解成几个小的、管理得当的部分。
- 避免过度匹配:确保正则表达式不会匹配到超出预期范围的文本。使用锚点(如
^
和$
)来限定匹配的开始和结束位置。 - 性能考量:对于要在大量文本上执行的正则表达式,要考虑其性能影响。在可能的情况下,使用字符串的内建方法,如
startswith()
,endswith()
,find()
或in
运算符,因为它们通常比正则表达式更快。
基本使用
-
说明
-
相关函数
-
match
- 从开头进行匹配,找到一个立即返回正则对象的结果,没有返回None
1
2
3
4
5# pyhton 依赖此模块完成正则功能
import re
# 从开头进行匹配,找到一个立即返回正则对象的结果,没有返回None
m = re.match('abc', 'abchelloabc') - 可以使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式
匹配对象方法 描述 group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
- 从开头进行匹配,找到一个立即返回正则对象的结果,没有返回None
-
search
- 匹配全部内容,任意位置,只要找到,立即返回正则结果对象,没有返回None
re.match
与re.search
的区别:
re.match
只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search
匹配整个字符串,直到找到一个匹配。1
2
3
4
5
6
7
8
9
10
11
12# pyhton 依赖此模块完成正则功能
import re
# 匹配全部内容,任意位置,只要找到,立即返回正则结果对象,没有返回None
m = re.search('abc', 'helloabc')
if m:
print('ok')
# 获取匹配的内容
print(m.group())
# 获取匹配的位置
print(m.span())- 可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式
匹配对象方法 描述 group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
-
findall
- 匹配所有内容,返回匹配的结果组成的列表,没有返回None
- 多个匹配模式,返回元组列表
1
2
3
4
5
6
7
8
9
10
11import re
# 匹配所有内容,返回匹配的结果组成的列表,没有返回None
f = re.findall('abc', 'abcddgasabckjjghlabc')
if f:
print(f)
# 多个匹配模式,返回元组列表
result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
print(result)
# [('width', '20'), ('height', '10')]
-
compile
-
根据字符串生成正则表达式的对象,拥有特定正则匹配,通过match 、search、findall匹配
1
2
3
4
5
6
7
8
9
10
11import re
# 根据字符串生成正则表达式的对象
c = re.compile('abc')
# 然后进行特定匹配
# m = c.match('abcdefghigl')
m = c.search('abcdefghigl')
if m:
print(m)
print(c.findall('abcfdasdssabc'))将re模块中的match 、search、findall方法的处理过程分为了两步完成
-
-
-
单个字符
模式 描述 普通字符 就是一对一的完全匹配 . 匹配除了换行( '\n'
)的任意字符[] 匹配[]中间的任意一个字符 [a-z] 匹配a到z的任意字符 [0-9] 匹配0到9的任意字符 [^abc] 匹配除abc之外的任意字符 \d 匹配任意数字,等价于 [0-9] \D 匹配任意非数字字符,等价于 [^0-9]
\w 匹配数字、字母、中文、下划线等(就是字的意思) \W 匹配\w之外的所有字符 \s 匹配任意空白字符,如:空格、\t、\n、\r、\f \S 匹配任意非空字符,即:\s之外的所有字符 \b 匹配一个单词边界,如:开头、结尾、标点、空格等 \B 匹配非单词边界 -
次数控制
模式 描述 * 前面的字符可以是任意次,正则的匹配默认是贪婪的 + 前面的字符串至少是一次 ? 匹配至多一次,0次或1次 {m} 匹配固定的m次 {m,} 匹配至少m次 {m,n} 匹配m到n次,在m和n之间尽量取多 {m,n}? 匹配m到n次,在m和n之间尽量取少 正则的匹配默认是贪婪的
-
边界限定
模式 描述 ^ 以指定内容开头 $ 以指定内容结尾 1
2
3
4
5
6
7
8
9
10
11
12
13
14import re
# 以指定内容开头
# c = re.compile(r'^abc')
# 以指定内容结尾
# c = re.compile(r'abc$')
# 同时限制开头和结尾
c = re.compile(r'^abc$')
s = c.search('abc')
if s:
print('ok')
print(s.group()) -
分组匹配
模式 描述 a|b 匹配a或b,具有最低的优先级 (re) 表示一个整体,可以确定优先级;对正则表达式分组并记住匹配的文本 (?:re) 类似 (re),但是只表示一个整体,不表示分组 1
2
3
4
5
6
7
8
9
10
11
12
13
14import re
# | 表示或,具有最低的优先级
# () 表示一个整体,可以确定优先级
# () 还有分组匹配的作用,下次再讲
# c = re.compile(r'ab|cd')
# c = re.compile(r'a[bc]d')
c = re.compile(r'a(hello|world)d')
s = c.search('ahellod')
if s:
print('ok')
print(s.group()) -
正向先行断言
1
2
3
4
5
6
7
8
9import re
s = """
废%卢$刺&/蝟@猫@=菠+&萝#包#-小-说【t/-X<t+提……取<群%:=】7#-5=6%1%-3-3#7&2|6 “卡赞也一起去吧,号角峰是大冰川最高
"""
if m := re.search(r'废.*?(?=\s)', s):
print(m.group())(?=\s)
是一个正则表达式的语法,被称为正向先行断言(Positive Lookahead)。在正则表达式中,先行断言用来指定一个位置,这个位置必须满足某个条件,但不包括在匹配结果中。- 具体来说:
(?=...)
是正向先行断言的结构,其中...
是你希望断言的部分。\s
是一个特殊的字符类,匹配任何空白字符,包括空格、制表符、换行符等。
练习
- 若匹配有特殊正则含义的字符怎么办,如:\d
- 友情提醒:转移问题(python中转义一次、正则解析转义一次)
- 验证一个字符串是否是正确的邮箱格式
- 验证一个字符串是否是正确的url格式
思路
- 以功能为向导
- 写出符合规则的若干字符串
- 写一点测一点,不断调整
- 最终完成功能