1. 什么是正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配
正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特殊字符,以及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑
2. 字符串匹配方法
2.1 re.match()
re.match():尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None
import re
str = "张三李四王五赵六李四"
# match():只从开头匹配,不成功直接返回None
result = re.match("李四",str)
print(result) #None
2.2 re.search()
re.search():扫描整个字符串并返回第一个成功的匹配
import re
str = "张三李四王五赵六李四"
# search():匹配的是整个字符串
result = re.search("李四",str)
print(result) #<re.Match object; span=(2, 4), match='李四'>
# span():返回匹配字符串所在位置
print(result.span()) #(2, 4)
# group():返回匹配内容
print(result.group()) #李四
# groups():返回一个包含所有小组字符串的元组,从1到所含的小组号
print(result.groups()) #()
2.3 re.findall()
re.findall():返回所有成功的匹配字符串
import re
str = "张三李四王五赵六李四"
# findall():返回所有匹配的字符串
result = re.findall("李四",str)
print(result) #['李四', '李四']
3. 替换和分割
3.1 re.sub()
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)
3.2 re.split()
re.split(pattern, string[, maxsplit=0, flags=0]):
- pattern:匹配的正则表达式
- string:要匹配的字符串
- maxsplit: 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数
- flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
>>>import re
>>> re.split('\W+', 'runoob, runoob, runoob.')
['runoob', 'runoob', 'runoob', '']
>>> re.split('(\W+)', ' runoob, runoob, runoob.')
['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']
>>> re.split('\W+', ' runoob, runoob, runoob.', 1)
['', 'runoob, runoob, runoob.']
4. 正则符号
4.1 第一类符号
-
[ ]:
- 用于表示一组字符,如果^是第一个字符,则表示的是一个补集
- 如[0123]、[zxcv]、[‘@#¥]表示的是有限个字符
- [0-9]、[a-z]表示的是字符集
- [^0-9]表示的事除了数字外的字符
import re s = "afo3oir45oij890aouih" result1 = re.findall("[1234][3456]",s) result2 = re.findall("[a-z][0-3][a-z]",s) result3 = re.findall("[^a-z][0-9][^a-z]",s) print(result1) #['45'] print(result2) #['o3o'] print(result3) #['890']
-
|:
- a|b,表示匹配a或者b
-
():
- (word1|word2|word3),表示要么是word1,要么是word2,要么是word3
- 一个()代表是一组,按照出现次序从1排列,若想调用分组排序,可用group(数字)
- ?P<名字>可以给分组定义自己的名字
import re email = "1123971628@qq.com" result = re.match(r"\w{5,20}@(163|126|qq)\.(com|cn)",email) print(result) #<re.Match object; span=(0, 17), match='1123971628@qq.com'>
4.2 第二类符号
-
*、+、?:
- "*"用于将前面的模式匹配0次或多次,>=0
- "+"用于将前面的模式匹配1次或多次,>=1
- "?"用于将前面的模式匹配0次或1次,0或1
import re s = "afo3oir45oij890aouih" result2 = re.findall("[a-z][0-9]*[a-z]",s) print(result2) #['af', 'o3o', 'ir', 'oi', 'j890a', 'ou', 'ih'] result2 = re.findall("[a-z][0-9]+[a-z]",s) print(result2) #['o3o', 'r45o', 'j890a'] result2 = re.findall("[a-z][0-9]?[a-z]",s) print(result2) #['af', 'o3o', 'ir', 'oi', 'ao', 'ui']
-
{m}、{m,}、{m,n}:
- "{m}"用于验证将前面的模式匹配m次
- "{m,}"用于验证将前面的模式匹配m次或者多次
- "{m,n}"用于验证将前面的模式匹配大于等于m次并且小于等于n次
import re # 验证是否为qq号码 s = "1123971638" result = re.findall("[1-9][0-9]{5,11}",s) print(result) #['1123971638'] result = re.findall("[1-9][0-9]{5}",s) print(result) #['112397'] result = re.findall("[1-9][0-9]{5,}",s) print(result) #['1123971638']
4.3 第三类符号
-
.、^、$:
- "."用于匹配除换行符(\n)之外的所有字符,如果想要表示".",则可使用"."表示
- "^"用于匹配字符串的开始,即行首,匹配时从头开始匹配
- "$"用于匹配字符串的末尾,即行尾,一直匹配到结尾,如果末尾有\n,就匹配\n前面的那个字符
import re # 验证是否为qq号码 s = "1123971628386045673" result = re.findall("[1-9][0-9]{4,10}",s) print(result) #['1123971638'] result = re.findall("^[1-9][0-9]{4,10}$",s) print(result) #[] s = "1123971628" result = re.findall("^[1-9][0-9]{4,10}$",s) print(result) #['1123971628']
4.4 第四类符号
-
\A、\Z、\b、\B、\d、\D、\S、\w、\W
- \A:表示从字符串的开始处匹配
- \Z:表示从字符串的结束处匹配,如果存在换行,只匹配到换行前的结束字符串。
- \b:匹配一个单词边界,也就是指单词和空格间的位置。例如,’py\b’可以匹配"python"中的'py'文件,但不能匹配"openpyx1"中的’py'
- \B:匹配非单词边界。’py\b’可以匹配"openpyx1"中的’py',但不能匹配"python”中的’py'文件
- \d:匹配任意数字,等价于[0-9]
- \D:匹配任意非数字字符,等价于["\d]
- \s:匹配任意空白字符,等价于[\t\n\r\f]
- \S:匹配任意非空白字符,等价于[~\s]
- \w:匹配任意字母数字及下划线,等价于[a-zA-Z0-9]
- \W:匹配任意非字母数字及下划线,等价于[\w]
- \:匹配原义的反斜杠\
5. 贪婪匹配与惰性匹配
Python里数量词默认是贪婪的(在少数语言中也可能是默认非贪婪),总是尝试匹配尽可能多的字符
非贪婪则相反,总是尝试匹配尽可能少的字符
在"*"、"?"、"+"、"{m,n}"后面加上"?",使贪婪变成非贪婪