正则表达式常用的匹配规则
模式描述****一般字符****.匹配除换行符"\n"和"\r"之外的任意字符,在re.S模式下则能匹配任意字符\转义字符,使下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符,如果原始字符串中含有* . ? + $ ^ [ ] ( ) { } | \,需要在前面加转义字符\才能正确表示,或者在字符串前面加个r房子转义[…]字符集,用来表示一组字符,对应的位置可以是字符集中任意一个字符,字符集中的字符可以逐个列出,也可以给出范围如[abc]或[a-c],所有的特殊字符在字符集中都失去本原有的含义,需要加\进行转义;常见的字符集[0-9]、[a-z]、[A-Z]、^[\u4e00-\u9fa5]*$[^…]在字符集内的开头加入非,表示匹配不在字符集内的其他任意字符,如[^abc]表示匹配除abc之外的任意字符****预定义字符集(可以写在字符集[…]中)****\d匹配任意数字,等价于[0-9]\D匹配任意非数字的字符,等价于[^\d]\s匹配空白字符,等价于[\t\n\r\f],如\t(Tab)、\r(回车)、’ '(空格)、\f(换页符)、\n(换行符)、\v(垂直制表符)\S匹配非空白字符,等价于[^\s]\w匹配字母数字及下划线,等价于[A-Za-z0-9_]\W匹配非字母数字及下划线的其他字符,等价于[^A-Za-z0-9_]****数量词(用在字符或(…)之后)*****匹配前一个字符、子表达式0次或多次,例如abc*能匹配ab,也能匹配abc、abcc,*等价于{0,}+匹配前一个字符、子表达式1次或多次,例如abc+,能匹配abc、abcc,但是不能匹配到ab,+号前的字符至少要匹配一次,+等价于{1,}?匹配前一个字符、子表达式0次或1次,例如do(es)?可以匹配到do或does,?等价于{0,1}{n}精确匹配前一个字符、子表达式n次,例如ab{2}c可以匹配到abbc,n为非负整数{n,}匹配前一个字符、子表达式至少n次(即[n,+∞]),例如ab{2,}c可以匹配到abbc或abbbbbbbc,n为非负整数{,n}匹配前一个字符、子表达式至多n次(即[0,n]),例如ab{,2}c可以匹配到ac、abc或abbc,n为非负整数{n,m}匹配前一个字符、子表达式最少匹配n次,最多m次(即[n,m]),例如ab{1,2}c可以匹配到abc或abbc,n, m为非负整数,且n<=m*?, +?, ??默认情况下*、+和?的匹配模式是贪婪模式,即会尽可能对的匹配符合规则的字符,*?、+?和??表示启用对应的非贪婪模式。如对于字符串"Pythonnn",正则表达式Python+能匹配大整个字符串,而Python+?则匹配Python{n,m}?同上,启用非贪婪模式,即只匹配n次,n, m为非负整数,且n<=m****边界匹配(不消耗待匹配字符串中的字符)****^匹配字符串的开头,在多行模式下(re.M)匹配每一行的开头,如^abc可以匹配abc$匹配字符串的末尾,在多行模式下(re.M)匹配每一行的末尾,如abc$可以匹配abc\A仅匹配字符串开头,如\Aabc可以匹配abc\Z仅匹配字符串末尾,如果存在换行,只匹配到换行前的结束字符串,如abc\Z可以匹配abc\z仅匹配字符串末尾,如果存在换行,同时还会匹配到换行符\b匹配单词边界,也就是指单词和空格间的位置,如er\b可以匹配到never中的er,但不能匹配到verb中的er\B匹配非单词边界,也就是指单词和空格间的位置,如er\B可以匹配到verb中的er,但不能匹配到never中的er,等价于[^\b]\G匹配最后匹配完成的位置****逻辑、分组****|左右表达式任意匹配一个,类似于"或"。总是先尝试匹配左边的表达式,一旦成功匹配就跳过匹配右边的表达式;如果|没有被包括在()中,则它的范围是整个表达式。如123|456能匹配到123、456(…)匹配圆括号中的正则表达式,或者指定一个子组的开始和结束位置,被括起来的表达式将作为分组,从表达式的左边开始每遇到一个分组的左括号’(’,编号+1;另外分组表达式作为一个整体,后面可以接数量词;表达式中的|也只能在该组中生效。如(abc){2}能匹配到abcabc,而a(123|456)c能匹配到a123c、a456c(?P<name>...)给分组命名,除了愿有你的编号外在指定一个额外的别名,通过分组名字name既可以访问到子组匹配的字串,例如(?P<id>abc){2}能够匹配到abcabc\<number>引用序号为<number>对应的子组所匹配到的字符串,子组的序号从1开始计算;如果序号以0开头,或者3个数字的长度,那么不会被引用对应的子组,而是用于匹配八进制数字所表示的ASCII码值所对应的字符。例如(.+) \1会匹配"python python" 或 “66 66”,但不会匹配holysll"(?P=name)引用别名为<name>的分组匹配到的字符串,如(?P<id>\d)abc(?P=id)能够匹配到1abc1、5abc5****特殊构造(不作为分组)****(?:...)(…)的不分组版本,用于使用| 或后接数量词。如(?:abc){2}能匹配abcabc(?aiLmsux)aiLmsux的每个字符代表一种匹配模式,(? 后可以紧跟着 ‘a’,‘i’,‘L’,‘m’,‘s’,‘u’,‘x’ 中的一个或多个字符,只能在正则表达式的开头使用,如(?i)abc匹配模式是忽略大小写,能够匹配abc、Abc、aBc、abC、ABc、AbC、aBC、ABC(?#...)#后的内容将作为主食被忽略,如abc(?#comment)123能够匹配abc123(?=...)之后的字符串内容需要匹配表达式才能匹配成功,不消耗字符创的内容。如a(?=\d)能匹配后面全是数字的a(?!...)之后的字符串内容需要不匹配表达式才能匹配成功,不消耗字符创的内容。如a(?!\d)能匹配后面不是数字的a(?<=...)之前的字符串内容需要匹配表达式才能匹配成功,不消耗字符创的内容。如a(?<=\d)能匹配前面是数字的a(?<!...)之前的字符串内容需要不匹配表达式才能匹配成功,不消耗字符创的内容。如a(?<!\d)能匹配后面不是数字的a(?(id/name)yes-pattern|no-pattern)如果序号为id/别名为name的组匹配到字符,则需要尝试yes-patteren匹配规则,否则需要尝试no-pattern匹配规则,no-pattern是可选可省略。如(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$) 是一个邮件格式的正则表达式,可以匹配<lucy@outlook.com>和lucy@outlook.com,但不会匹配<lucy@outlook.com或lucy@outlook.com>正则表达式的匹配模式:
flags描述re.I(IGNORECASE)忽略大小写,使匹配对大小写不敏感re.L(LOCALE)做本地化识别(locale-aware)匹配re.M(MULTILINE)多行匹配模式,影响^ 和 $re.S(DOTALL)使 . 匹配包括换行在内的所有任意字符re.U根据Unicode字符集解析字符,这个标志影响\w、\W、\b、\B、\d、\D、\s、\Sre.X(VERBOSE)该标志通过给予更灵活的格式以便将正则表达式更易于理解,详细表达式re.A只匹配ASCII字符re分组匹配对象的方法:
方法描述group([group1, …])用于获得一个或者多个分组匹配的字符串,当要获得整个匹配的子串时,使用group()或group(0);groups()等价于(group(1), group(2), …)start([group])用于获取分组匹配的子串在整个字符串的起始位置(子串第一个字符的索引),参数值默认为0end([group])用于获取分组匹配的子串在整个字符串的结束位置(子串最后一个字符的索引+1),参数值默认为0span([group])返回(start(group), end(group));span(0) 返回匹配成功的整个子串的索引;span(1) 返回第一个分组匹配成功的子串的索引re模块中一些重要的函数:
search:扫描整个字符串并返回第一个成功的匹配,匹配成功返回一个匹配的对象,否则返回None。search()函数语法:re.search(pattern, string[, flags]) 其中,参数pattern是匹配的正则表达式;参数string是需要匹配的字符串;参数flags是标志位,用于控制正则表达式的匹配模式。
import re res = re.search(r'www\.(.*)\.(.{3})', 'www.baidu.com', re.I) # 忽略大小写 if res: print(res.groups()) # 从分组1算起 print("分组0:") print(res.group()) print(res.group(0)) print("分组1:") print(res.group(1)) print(res.start(1)) print(res.end(1)) print(res.span(1)) print("分组2:") print(res.group(2)) print(res.start(2)) print(res.end(2)) print(res.span(2)) # 结果 ''' ('baidu', 'com') 分组0: www.baidu.com www.baidu.com 分组1: baidu 4 9 (4, 9) 分组2: com 10 13 (10, 13) ''' match:尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。match()函数语法:re.match(pattern, string[, flags])其中,参数pattern是匹配的正则表达式;参数string是需要匹配的字符串;参数flags是标志位,用于控制正则表达式的匹配模式。
import re res = re.search(r'baidu', 'www.baidu.com', re.I) if res: print("search匹配成功") print(res.group()) else: print("search匹配失败") rem = re.match(r'baidu', 'www.baidu.com', re.I) if rem: print("match匹配成功") print(rem.group()) else: print("match匹配失败") # 结果 ''' search匹配成功 baidu match匹配失败 ''' compile:用于编译正则表达式,生成一个正则表达式(pattern)对象,供match()和search()这两个函数使用。compile()函数语法:re.compile(pattern[, flags])其中,参数pattern是匹配的正则表达式;可选参数flags是匹配模式,用于控制正则表达式的匹配模式。
import re pattern = re.compile(r'\w+', re.I) res = pattern.search('www.baidu.com') if res: print("compile search匹配成功") print(res.group(0)) print(res.start(0)) print(res.end(0)) print(res.span(0)) else: print("compile search匹配失败") rem = pattern.match('www.baidu.com', 4, 8) if rem: print("compile match匹配成功") print(rem.group(0)) print(rem.start(0)) print(rem.end(0)) print(rem.span(0)) else: print("compile match匹配失败") # 结果 ''' compile search匹配成功 www 0 3 (0, 3) compile match匹配成功 baidu 4 9 (4, 9) ''' findall:在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。match 和 search 是匹配一次 findall 匹配所有。findall()函数语法:re.findall(pattern, string[, flags])其中,参数pattern是匹配的正则表达式;参数string是需要匹配的字符串;参数flags是标志位,用于控制正则表达式的匹配模式。
import re res = re.findall(r'\w+', 'Hello World!', re.I) print(res) # 返回的是一个列表 # 结果 ''' ['Hello', 'World'] ''' # 通过compile编译正则表达式 pattern = re.compile(r'\w+', re.I) rec = re.findall(pattern, 'Hello World!') print(rec) # 结果 ''' ['Hello', 'World'] ''' sub:将字符串中与模式pattern匹配的子串都替换为repl。sub()函数语法:re.sub(pattern, repl, string[, count=0, flags])其中,参数pattern是匹配的正则表达式;参数repl是替换的字符串,也可以是一个函数;参数string是需要匹配的字符串;可选参数count是模式匹配后替换的最大次数,默认0表示替换所有的匹配项;可选参数flags是标志位,用于控制正则表达式的匹配模式。
import re res0 = re.sub(r'\D', '', 'abc123#¥@', 0, re.I) # 把非数字部分删除 res1 = re.sub(r'\D', '', 'abc123#¥@', 1, re.I) res2 = re.sub(r'\D', '', 'abc123#¥@', 3, re.I) print(res0) print(res1) print(res2) # 结果 ''' 123 bc123#¥@ 123#¥@ ''' # 通过compile编译正则表达式 pattern = re.compile(r'\D', re.I) res = re.sub(pattern, '', 'abc123#¥@', 0) # 这时,不能传入flags匹配模式,而要在compile里传入 print(res) # 结果 ''' 123 ''' # repl是一个函数时,将匹配到的数字乘以2 def double(num): print(num.group('value')) value = int(num.group('value')) return str(value * 2) result = re.sub(r'(?P<value>\d+)', double, 'a1B23C456d7890') print(result) # 结果 ''' 1 23 456 7890 a2B46C912d15780 ''' split:按照能够匹配的子串将字符串分割后返回列表。split()函数语法:re.split(pattern, string[, maxsplit=0, flags=0])其中,参数pattern是匹配的正则表达式;参数string是需要匹配的字符串;可选参数maxsplit是分割次数,默认为0表示不限制次数;可选参数flags是标志位,用于控制正则表达式的匹配模式。
import re res1 = re.split('\W+', 'www.baidu.com') res2 = re.split('(\W+)', 'www.baidu.com') res3 = re.split('\W+', 'www.baidu.com', 1) # 分割一次 res4 = re.split('p*', 'www.baidu.com') # 匹配不到的正则表达式 print(res1) print(res2) print(res3) print(res4) # 结果 ''' ['www', 'baidu', 'com'] ['www', '.', 'baidu', '.', 'com'] ['www', 'baidu.com'] ['', 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', ''] ''' escape:将字符串中所有的特殊字正则表达式字符转义,当大量主要加反斜杠\进行转义时,这个函数很有用,避免一些不必要的错误,实际上功能有点类似正则表达式前面加r。escape()函数语法:re.escape(pattern)
import re res = re.escape('www.python.org') print(res) result = re.findall(re.escape('.py'), "python www.python.org proxy.py") print(result) # 结果 ''' www\.python\.org ['.py', '.py'] '''手写正则邮箱地址:
import re email_addr = 'Please reply this email to <abc23@sample.com.cn>' # tool.chinaz.com给出的是:\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14} pattern = re.compile(r'([\w\.-]+)@([\w\.-]+)(\.[\w\.]+)') res = re.search(pattern, email_addr) if res: print(res.group) else: print("匹配失败") # 结果 ''' abc23@sample.com.cn '''常用正则表达式
目标表达式中文字符[\u4e00-\u9fa5]双字节字符(包括汉字在内)[^\x00-\xff]空白行\n\s*\rEmail地址\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}网址URL[a-zA-z]+://[^\s]* 或 ^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+国内电话号码[0-9-()()]{7,18}国内手机号码0?(13|14|15|17|18|19)[0-9]{9}QQ号码[1-9]([0-9]{5,11})邮政编码\d{6}身份证号^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$日期格式\d{4}(\-|\/|.)\d{1,2}\1\d{1,2}IP地址(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)整数-?[1-9]\d*正整数[1-9]\d*负整数-[1-9]\d*正浮点数[1-9]\d*.\d*|0.\d*[1-9]\d*负浮点数-([1-9]\d*.\d*|0.\d*[1-9]\d*)用户名(字母、数字、下划线、-、以及中文)[A-Za-z0-9_\-\u4e00-\u9fa5]+