Python中的正则表达式
一正则表达式使用1.什么是正则表达式正则表达式其实就是一套固定的规则这套规则限制着字符串或者说是在过滤字符串比如规则 \d{11}匹配11位数字用来验证手机号规则 \w\w.\w匹配邮箱格式核心用途验证:判断字符串是否符合规则(比如手机号、邮箱、身份证号格式是否正确);查找:从文本中找出所有符合规则的字符串(比如从新闻中提取所有日期);提取:从匹配结果中提取关键信息(比如从邮箱中提取用户名);替换:替换文本中符合规则的内容(比如过滤文本中的特殊字符)。使用正则表达式之前需要进行导包import re使用正则表达式的核心流程定义规则-执行匹配-提取结果import re #导入正则表达式模块 res re.match(rh\w,hello world) if res: print(res.group()) else: print(匹配失败)re.match()只会根据字符的开头进行匹配如果开头错误会直接失败失败会返回None。2.匹配单个字符的规则符号符号 / 写法匹配规则补充说明.匹配除换行符\n外的任意单个字符开启re.DOTALL标志后可匹配包含换行符在内的所有字符[abc]匹配方括号内列举的任意一个字符集合内为 “或” 逻辑绝大多数元字符如.、*在集合内会失去特殊含义仅作为普通字符匹配[a-z]匹配指定字符范围内的任意一个字符用-连接起止字符支持[0-9]、[A-Za-z]等组合-放在集合首尾时仅作为普通横杠字符匹配[^abc]匹配不在方括号内的任意一个字符^必须放在集合开头才表示取反放在集合中间时仅作为普通字符匹配\d匹配任意单个数字字符ASCII 模式等价于[0-9]Python 3 默认 Unicode 模式还会匹配全角数字等开启re.ASCII后仅匹配半角数字\D匹配任意单个非数字字符\d的取反形式ASCII 模式等价于[^0-9]\w匹配任意单个单词字符ASCII 模式等价于[A-Za-z0-9_]Unicode 模式下还会匹配中文等语言文字\W匹配任意单个非单词字符\w的取反形式ASCII 模式等价于[^A-Za-z0-9_]\s匹配任意单个空白字符包含空格、制表符\t、换行符\n、回车符\r、换页符\f、垂直制表符\v\S匹配任意单个非空白字符\s的取反形式\转义符将正则元字符转义为普通字面字符用于匹配符号本身例如\.匹配字面点号、\[匹配左中括号、\\匹配反斜杠本身3.匹多个字符的规则符号符号 / 写法匹配规则补充说明*匹配前面的字符 / 分组 0 次或多次贪婪模式尽可能多地匹配目标内容等价写法为{0,}匹配前面的字符 / 分组 1 次或多次贪婪模式被匹配内容至少出现 1 次等价写法为{1,}?匹配前面的字符 / 分组 0 次或 1 次贪婪模式用于标记可选内容等价写法为{0,1}{n}匹配前面的字符 / 分组恰好 n 次n 为非负整数例如\d{4}可匹配连续 4 位数字{n,}匹配前面的字符 / 分组至少 n 次贪婪模式匹配次数无上限优先匹配尽可能多的内容{n,m}匹配前面的字符 / 分组 n 到 m 次贪婪模式包含 n 次和 m 次边界优先匹配更多次数量词?将贪婪量词转为非贪婪惰性模式尽可能少匹配常见写法*?、?、??、{n,m}?正则默认贪婪匹配追加?后转为最少匹配( )分组将括号内的多字符视为一个整体可配合量词实现重复匹配例如(ab)可匹配ab、abab等同时会捕获分组内的匹配结果OK那现在就可以施展他们两的组合技了\d* 匹配任意数量的数字字符\d 匹配任意数量的数字字符。# \d* 匹配任意数量的数字字符 res1 re.match(\d*,123abc) print(res1.group()) # \d 匹配任意数量的数字字符 res2 re.match(\d,123abc) print(res2.group())他两的区别就是d*的结果可以为0以上的结果d只能为1以上的结果\d? 最多匹配一个数字字符# \d? 最多匹配一个数字字符 res re.match(\d?,123abc) print(res.group())手机格式验证phone1 13212345678 phone2 1321234567 phone3 132abcdefgh res1 re.match(\d{11},phone1) print(res1.group()) # 输出13212345678 res2 re.match(\d{11},phone2) print(res2.group()) # 报错AttributeError res3 re.match(\d{11},phone3) print(res3.group()) # 报错AttributeError4.核心规则匹配开头和结尾用^和$限定字符串的开头和结尾确保整个字符串完全符合规则避免部分匹配。其实核心的意思就是打假^打假开头防止尾部符合开头不符合规则$符号打假尾部防止开头符合尾部不符合。邮箱格式验证# 邮箱规则数字/字母/下划线开头后面是数字字母.后面是2-4位字母 #这里的\.表示只匹配.;如果写.表示匹配除换行符以外的所有字符 pattern r^\w\w\.\w{2,4}$ # 要验证的邮箱 email1 abc123qq.com # 结果abc123qq.com email2 abc123.xyz # 结果abc123.xyz email3 abc123.com # 结果格式错误 email4 abc123qq.com.cn # 结果格式错误 for email in [email1,email2,email3,email4]: res re.match(pattern,email) if res: print(res.group()) else: print(格式错误)5.核心规则匹配分组进阶用将部分规则分组可实现“多选一”或“引用分组结果”适合复杂匹配场景。5.1多选一|规则规则1|规则2|规则3匹配任意一个符合的规则只要符合其中一条就能输出否则报错。pattern r(red|blue|black) string1 blue string2 green res1 re.match(pattern,string1) res2 re.match(pattern,string2) print(res1.group()) #输出blue print(res2.group()) #不匹配程序报错5.2引用分组结果\num用\num引用前面第num个分组匹配的内容比如匹配成对的HTML标签适合成双成对出现的字符。张三在前面出现过后面就使用 \数字 来代替这里注意数字取决于第几个分组而分组使用来表示分组。#htmllogin/html pattern r(\w)\w/\1 string1 htmllogin/html string2 htmllogin/body res1 re.match(pattern,string1) res2 re.match(pattern,string2) print(res1.group()) #输出htmllogin/html print(res2.group()) #不匹配程序报错二常用函数回顾re.match()功能从字符串开头开始匹配开头不符合就返回None。res1 re.match(th,this is a good day) print(res1.group()) #输出th res2 re.match(th,a good day) print(res2.group()) #报错2.1核心函数re.search()——全局找第一个匹配功能·search()会遍历整个字符串不管开头是否匹配只要找到第一个符合规则的就返回结果如果没有就返回None相当于文档里面的查找功能。res1 re.search(good,this is a good day) print(res1.group()) #输出good res2 re.search(is,this is a good day) print(res2.group()) #输出is(出现多次只会返回第一个) res3 re.search(cc,this is a good day) print(res3) #输出None2.2核心函数re.findall()——找所有匹配项返回列表功能findall()会遍历整个字符串找到所有符合规则的非重叠子串并将所有获取到的结果以列表的形式返回如果没有找到就返回空列表。res1 re.findall(r\d,abcd1234#$) print(res1) #输出[1, 2, 3, 4] res2 re.findall(r\w{3},good123ABC_xyz) print(res2) #输出[goo, d12, 3AB, C_x] res3 re.findall(r\d,abcd#$) print(res3) #输出[]2.3核心函数re.sub()——替换匹配项功能sub()会遍历字符串将所有匹配到规则的子串替换成指定内容可以指定替换次数默认情况下替换所有匹配项。res1 re.sub(is,am,hello,everyone! this is a good day!) print(res1) #输出hello,everyone! tham am a good day! res2 re.sub(is,am,hello,everyone! this is a good day!,count1) print(res2) #输出hello,everyone! tham is a good day!只替换第一个 res3 re.sub(r\d,*,今天是第23天温度是36°湿度是48%) print(res3) #输出今天是第**天温度是**°湿度是**% res4 re.sub(r\W,,sajs%^$sa) print(res4) #输出sajssa(删除所有特殊符号)三贪婪匹配非贪婪匹配3.1什么是贪婪匹配/非贪婪匹配正则贪婪模式默认量词如*、、{mn}会尽可能的匹配多的字符一直到无法匹配为止。非贪婪模式在量词后加量词会尽可能匹配少的字符满足规则即可。3.2关键前提只影响量词的匹配行为受影响的量词不受影响的规则.、\d、[a-z]等单个字符匹配规则。3.3贪婪模式正则默认是贪婪模式不用额外加任何符号量词会自动匹配尽可能多的字符。这里可以理解为规则范围内取最大值作为标准。res1 re.match(r\d*,1234abcd) print(res1.group()) #输出1234 res2 re.match(r\d,1234abcd) print(res2.group()) #输出1234 res3 re.match(r\d{2,3},1234abcd) print(res3.group()) #输出1233.4非贪婪模式量词后面加能少拿就少拿。这里可以理解为规则范围内取最小值作为标准。res1 re.match(r\d*?,1234abcd) print(res1.group()) #输出空字符串 res2 re.match(r\d?,1234abcd) print(res2.group()) #输出1 res3 re.match(r\d{2,3}?,1234abcd) print(res3.group()) #输出12重点实例模糊匹配中的差异注意需要加在量词后面res_greedy re.match(ra.*b,string) res_non_greedy re.match(ra.*?b,string) print(res_greedy.group()) #输出a123b123b print(res_non_greedy.group()) #输出a123b3.5什么时候适合使用非贪婪模式常见场景1.提取“最近匹配”的内容如上面的a.*?b提取a到最近的b2.避免匹配范围“过度扩大”如提取HTML标签时避免把多个标签当成一个3.明确需要“最少匹配”的场景如匹配2-5个数字只需要前2个示例提取HTML标签中的内容非贪婪必用string div第一部分/divdiv第二部分/div res_greedy re.match(rdiv.*/div,string) res_non_greedy re.match(rdiv.*?/div,string) print(res_greedy.group()) #输出div第一部分/divdiv第二部分/div print(res_non_greedy.group()) #输出div第一部分/div