正则表达式
正则表达式是一个特殊的字符序列,帮助检查一个字符串是否与某种模式匹配。
用途
- 检测一个输入的字符串是否合法 ---- Web开发项目 表单验证
- 用户输入内容的时候,提前做检测
- 能够提高程序的效率,减轻服务器的压力
- 从大文件中找到所有符合规则的内容
- 能够高效的从一大段文字中快速找到符合规则的内容
1、元字符和量词
元字符 描述
-
^ 匹配字符串的开头
-
$ 匹配字符串的末尾。
-
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
-
[().*+?] 这些内容在字符组中会取消他们的特殊意义
-
[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
-
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
-
\s 匹配任意空白字符,相当于[\t\n\r\f](制表符、回车、空格)。
-
\S 匹配任意非空字符
-
\d 匹配任意数字,等价于 [0-9]。
-
\D 匹配任意非数字
-
\w 匹配数字字母下划线
-
\W 匹配非数字字母下划线
-
\A 匹配字符串开始
-
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
-
\z 匹配字符串结束
-
\G 匹配最后匹配完成的位置。
-
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
-
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
-
\n, \t, 等。 匹配一个换行符。匹配一个制表符, 等
-
\1...\9 匹配第n个分组的内容。
-
\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。
-
a| b 匹配a或b,匹配a成功就不匹配b,如果a、b相似,将长的写在前面
-
(re) 匹配括号内的表达式,也表示一个组
-
(?: re) 类似 (...), 但是不表示一个组(取消这个组的优先显示)
-
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
-
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
-
(?imx: re) 在括号中使用i, m, 或 x 可选标志
-
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
-
(?#...) 注释.
-
(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
-
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
-
(?> re) 匹配的独立模式,省去回溯。
量词 描述
-
{ n} 匹配n个前面表达式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。
-
{ n,} 精确匹配n个前面表达式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。
-
{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
- * 匹配0个或多个的表达式。
- + 匹配1个或多个的表达式。
- ? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
贪婪匹配
.*?x 表示匹配任意字符,任意多次数,遇到最后一个x才停下来
非贪婪匹配
.*?x 表示匹配任意字符,任意多次数,遇到第一个x才停下来
2、re模块
re 模块使 Python 语言拥有全部的正则表达式功能。
compile 函数
根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
a、用途:
标签匹配
用户输入匹配
- match() 从开头匹配一次
- search() 只匹配一次
- findall() 查找所有
- sub() 替换
- split() 切割
b、方法:
re.compile(正则) 方法
加入同一个正则表达式要被使用多次,节省了多次解析同一个正则表达式的时间 (节省解析时间)
ret = re.compile(r'\d+')
res1 = ret.search('116afafe1561f')
res2 = ret.findall('116afafe1561f')
print(res1.group()) # 116
print(res2) # ['116', '1561']
re.finditer() 方法
返回一个迭代器,通过迭代取代一个变量,通过group提取(节省空间)
ret = re.finditer(r'\d+', '123afdsfa445')
print(ret) # <callable_iterator object at 0x0000018DB9A9B8C8>
for i in ret:
print(i.group())
# 输出
# 123
# 445
既节省时间,有节省空间
ret = re.compile(r'\d+')
res = ret.finditer('45fd6afd5a6f')
for r in res:
print(r.group())
输出:
45
6
5
6
re.findall方法
查找所有,按照完整的正则进行匹配,只是显示括号里匹配到的内容
re.search方法
扫描整个字符串并返回第一个成功的匹配。显示匹配到的第一个内容,可以通过group方法传参数来获取具体元组中的内容
函数语法
re.search(pattern, string, flags=0)
re.match函数
re.match 字符串的起始位置匹配一个模式,起始位置匹配不成功,match()就返回none。
函数语法
re.match(pattern, string, flags=0)
group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 描述
- group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
- groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
re.sub函数
替换字符串:通过正则表达式匹配的内容来进行替换
msg = "java:90 python:89 C++:99 VF:89"
result = re.sub(r'\d+','100',msg) # 将所有数字变成100
print(result)
# 利用函数将字符串中的数字+1
def func(temp):
num = int(temp.group())+1
return str(num)
result = re.sub(r'\d+',func,msg)
re.subn函数
替换,在sub的基础上返回一个元组,第一个是替换结果,第二个是替换次数
re.split 切割
result = re.split(r'[:\s]',msg) # 将分割的内容保存在字符串中
print(result)
使用()进行字符串分组
# 判断邮箱地址 163 或者 126 或者 qq
emails = '[email protected]'
res5 = re.match(r'\w{6,12}@(aa|163|126)\.(com|cn)$',emails) # 新版
print(res5)
# 分组提取区号 010-12121321
num = '010-5645616'
result = re.match(r'(\d{3}|\d{4})-(\d{7})',num) # 一个()代表一组,
print(result)
print(result.group())
print(result.group(1)) # 用group(1-9)提取数组
print(result.group(2))
# 提取标签里的内容
# <html>hello</html>
# <h1>world</h1>
msg = '<html>hello</html>'
msg1 = '<h1>world</h1>'
result = re.match(r'<\w+>(.+)</\w+>',msg1) # 前后标签内容不一样时也会匹配<html>adf</h1>
print(result)
print(result.group(1))
使用数字 \1...\9
msg2 = '<h1>world</h1>'
msg3 = '<html><h1>world</h1></html>'
result = re.match(r'<(\w+)>(.+)</\1>$',msg2)
print(result)
print(result.group(2))
result = re.match(r'<(\w+)><(\w+)>(.+)</\2></\1>$',msg3) # 太长使用数字容易混淆,用起名方式
print(result)
print(result.group(3))
正则起名字的方式 (?P
msg3 = '<html><h1>world</h1></html>'
result = re.match(r'<(?P<name>\w+)><(?P<name1>\w+)>(.+)</(?P=name1)></(?P=name)>',msg3)
re.group(name1)