正则表达式就是字符串的匹配规则,在多数编程语言里都有相应的支持,python里对应的模块是 re。

re的匹配语法有以下几种

  • re.match 从头开始匹配
  • re.search 匹配包含
  • re.findall 把所有匹配到的字符放到以列表中的元素返回
  • re.split 以匹配到的字符当做列表分隔符
  • re.sub 匹配字符并替换
  • re.fullmatch 全部匹配

 常用的表达式规则   红色加粗的为重要的常用的

  • '.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
>>> re.search('.','qasd')  #字母可以匹配
<re.Match object; span=(0, 1), match='q'>
>>> re.search('.','1asd')  #数字可以匹配
<re.Match object; span=(0, 1), match='1'>
>>> re.search('.','*asd')  #特殊字符可以匹配
<re.Match object; span=(0, 1), match='*'>
>>> re.search('..','*asd')  #想匹配几个字符,就加几个点
<re.Match object; span=(0, 2), match='*a'>
  • '^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
>>> re.search('^','qasd')
<re.Match object; span=(0, 0), match=''>
>>> re.search('^a','qasd')
>>> re.search('^a','abd')
<re.Match object; span=(0, 1), match='a'>
>>> re.search('^ab','abd')
<re.Match object; span=(0, 2), match='ab'>
>>> re.search('^b','abd') #没匹配到,无返回,相当于  re.match('b','abd')
  • '$' 匹配字符结尾, 若指定flags MULTILINE ,re.search('foo.$','foo1\nfoo2\n',re.MULTILINE).group() 会匹配到foo1
#匹配以什么结尾
>>> re.search('b$','abd')
>>> re.search('b$','ab')
<re.Match object; span=(1, 2), match='b'>
>>> re.search('b$','bab')
<re.Match object; span=(2, 3), match='b'>
#匹配格式
>>> re.match('b$','ab')
>>> re.match('b$','b')
<re.Match object; span=(0, 1), match='b'>
>>> re.match('b$','bob')
>>> re.match('b.b$','bob')
<re.Match object; span=(0, 3), match='bob'>
  • '*' 匹配字符开头,匹配*号前的字符0次或多次, re.search('a*','aaaabac') 结果'aaaa'
>>> re.search('a*','Alex') #匹配不到时,返回值为空
<re.Match object; span=(0, 0), match=''>
>>> re.search('a*','Alex').group()
''
>>> re.search('a*','alex').group()
'a'
>>> re.search('a*','aaaalex').group()
'aaaa'
>>> re.search('ab*','abaaex').group() #可以加两个字符,但事实上匹配的还是前一个字符
'ab'
>>> re.search('ab*','ababbaex').group()
'ab'
>>> re.search('ab*','abbbbaex').group()
'abbbb'
  • '+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
>>> re.search('a+','sdf')
>>> re.search('a+','abbaalex') 
<re.Match object; span=(0, 1), match='a'>
>>> re.search('a+','aaab')
<re.Match object; span=(0, 3), match='aaa'>
>>> re.search('.+','aaab') #'.' 是匹配除\n外任意字符,在这里就是全部匹配
<re.Match object; span=(0, 4), match='aaab'>
>>> re.search('ab+','aaab') #匹配 '+' 前的字符和最后一个字符
<re.Match object; span=(2, 4), match='ab'>
>>> re.search('ab+','aaabab')
<re.Match object; span=(2, 4), match='ab'>
>>> re.search('ab+','aaabbbbab')
<re.Match object; span=(2, 7), match='abbbb'>
>>> re.search('ab+','bbbbb') #匹配不到
  • '?' 匹配前一个字符1次或0次 ,re.search('b?','alex').group() 匹配b 0次
>>> re.search('a?','aaab')
<re.Match object; span=(0, 1), match='a'>
>>> re.search('a?','bbb')
<re.Match object; span=(0, 0), match=''>
  • '{m}' 匹配前一个字符m次 ,re.search('b{3}','alexbbbs').group() 匹配到'bbb'
>>> re.search('a{2}','ddd')
>>> re.search('a{2}','addd')
>>> re.search('a{2}','aaddd') #必须一次匹配两个
<re.Match object; span=(0, 2), match='aa'>
>>> re.search('a{2}','adaadd') #全局匹配
<re.Match object; span=(2, 4), match='aa'>
>>> re.search('a{2}','adaadd')
<re.Match object; span=(2, 4), match='aa'>
>>> re.search('.{2}','adaaadd') #'.' 是开头匹配两个
<re.Match object; span=(0, 2), match='ad'>
>>> re.search('[0-9]{2}','1234adaaadd') #匹配两个数字
<re.Match object; span=(0, 2), match='12'>
  • '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
>>> re.search('[a-z]','alex')
<re.Match object; span=(0, 1), match='a'>
>>> re.search('[a-z]{1,2}','alex') #尽可能匹配到最大
<re.Match object; span=(0, 2), match='al'>
>>> re.search('[a-z]{1,2}','a2lex')
<re.Match object; span=(0, 1), match='a'>
  • '|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
>>> re.search('alex|Alex','alex') #匹配 alex 或 Alex
<re.Match object; span=(0, 4), match='alex'>
>>> re.search('a|Alex','alex')  #匹配 a 或 Alex
<re.Match object; span=(0, 1), match='a'>
>>> re.search('[a|A]lex','alex') #匹配 alex 或 Alex
<re.Match object; span=(0, 4), match='alex'>
  • '(...)' 分组匹配, re.search("(abc){2}a(123|45)", "abcabca456c").group() 结果为'abcabca45'
>>> re.search('[a-z]+','alex123') 
<re.Match object; span=(0, 4), match='alex'>
>>> re.search('([a-z]+)([0-9]+)','alex123') #分别匹配小写字母和数字
<re.Match object; span=(0, 7), match='alex123'>
>>> re.search('([a-z]+)([0-9]+)','alex123').group()
'alex123'
>>> re.search('([a-z]+)([0-9]+)','alex123').groups() #将分别匹配出的结果分开
('alex', '123')
  • '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的,相当于re.match('abc',"alexabc") 或^
>>> re.search('\Aalex','alex789')  #相当于 re.search('^alex','alex789')、re.match('alex','alex789')
<re.Match object; span=(0, 4), match='alex'>
  • '\Z' 匹配字符结尾,同$
>>> re.search('[0-9]\Z','al***ex789peiqi562233')  #用法同 $
<re.Match object; span=(20, 21), match='3'>
  • '\d' 匹配数字0-9
>>> re.search('\d','alex789')
<re.Match object; span=(4, 5), match='7'>
>>> re.search('\d+','alex789')
<re.Match object; span=(4, 7), match='789'>
>>> re.search('\d+','alex789peiqi562233')
<re.Match object; span=(4, 7), match='789'>
  • '\D' 匹配非数字
>>> re.search('\D+','alex789peiqi562233')
<re.Match object; span=(0, 4), match='alex'>
>>> re.search('\D+','al***ex789peiqi562233')
<re.Match object; span=(0, 7), match='al***ex'>
  • '\w' 匹配[A-Za-z0-9] ,即匹配除特殊字符之外的所有
>>> re.search('\w','al***ex789peiqi562233')
<re.Match object; span=(0, 1), match='a'>
>>> re.search('\w','alex789peiqi562233')
<re.Match object; span=(0, 1), match='a'>
>>> re.search('\w+','al***ex789peiqi562233')
<re.Match object; span=(0, 2), match='al'>
>>> re.search('\w+','alex789peiqi562233')
<re.Match object; span=(0, 18), match='alex789peiqi562233'>
  • '\W' 匹配非[A-Za-z0-9],即匹配特殊字符
>>> re.search('\W','al***ex789peiqi562233')
<re.Match object; span=(2, 3), match='*'>
>>> re.search('\W+','al***ex789peiqi562233')
<re.Match object; span=(2, 5), match='***'>
  • '\s' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'
>>> s = 'alex\njack'
>>> re.search('\s',s)
<re.Match object; span=(4, 5), match='\n'>
>>> re.search('\s','alex\njack\tdd\rmack')
<re.Match object; span=(4, 5), match='\n'>
>>> re.findall('\s','alex\njack\tdd\rmack')
['\n', '\t', '\r']
  • '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}
>>> s = '1307042000005250613'
>>> re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<bron_year>\d{4})',s) #不分组输出
<re.Match object; span=(0, 10), match='1307042000'>
>>> re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<bron_year>\d{4})',s).groups() #涉及分组,就用 groups()
('130', '704', '2000')
>>> res = re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<bron_year>\d{4})',s)
>>> res.groupdict() #以字典形式输出
{'province': '130', 'city': '704', 'bron_year': '2000'}

 re匹配语法详解

  • re.match 匹配开头,从头开始,只匹配一个字符,匹配到就返回结果,匹配不到无返回
>>> re.match('[0-9]','abc1d3e') 
  • re.search(pattern, string, flags=0)

    根据模型去字符串中匹配指定内容,匹配单个

>>> re.search('[0-9]','abc1d3e') #从头开始匹配,全局匹配,匹配到一个就返回
<re.Match object; span=(3, 4), match='1'>
  • re.findall(pattern, string, flags=0)

    match and search均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall。

>>> re.findall('[0-9]','abc1d3e') #全局匹配,将所有匹配到的放入列表中返回
['1', '3']
>>> if match_res: 
...     match_res.group() #有返回值的时候,返回结果,没有返回值,会报错
...
'1'
  • re.sub(pattern, repl, string, count=0, flags=0)

    用于替换匹配的字符串,相比于str.replace功能更加强大

>>> re.sub('\d+','_','alex22jack23rain31jinxin50|mack-oldboy') #全部替换
'alex_jack_rain_jinxin_|mack-oldboy'
>>> re.sub('\d+','_','alex22jack23rain31jinxin50|mack-oldboy',count = 2) #只替换前两个
'alex_jack_rain31jinxin50|mack-oldboy'
  • re.split(pattern, string, maxsplit=0, flags=0)
>>> re.split('\d','alex22jack23rain31jinxin50')  #只取一个数字,所以有空返回值
['alex', '', 'jack', '', 'rain', '', 'jinxin', '', '']
>>> re.split('\d+','alex22jack23rain31jinxin50') #去所有的数字,因为最后一个数字后面没东西了,所以有一个空返回值
['alex', 'jack', 'rain', 'jinxin', '']
>>> re.split('\d+|#|-','alex22jack23rain31jinxin50#mack-oldboy') #以数字、# 、- 分隔
['alex', 'jack', 'rain', 'jinxin', '', 'mack', 'oldboy']
>>> re.split('\|','jinxin50|mack-oldboy') #'\' 是转译字符,为了以 '|' 分隔
['jinxin50', 'mack-oldboy']
>>> re.split('\\\\','xin50\\mack-oldboy') #想以 '\' 分隔,必须是四个 '\' 
['xin50', 'mack-oldboy']
>>> re.split('\\\\','xin50\mack-oldboy')
['xin50', 'mack-oldboy']

>>>s='9-2*5/3+7/3*99/4*2998+10*568/14'
>>>re.split('[\*\-\/\+]',s)  
['9', '2', '5', '3', '7', '3', '99', '4', '2998', '10', '568', '14']
>>> re.split('[\*\-\/\+]',s,3) #只分隔前三个
['9', '2', '5', '3+7/3*99/4*2998+10*568/14']
  • re.fullmatch(pattern, string, flags=0)

    整个字符串匹配成功就返回re object, 否则返回None

>>> re.fullmatch('alex','alex123') #必须完全匹配
>>> re.fullmatch('alex123','alex123') 
<re.Match object; span=(0, 7), match='alex123'>
>>> re.fullmatch('\w+@\w+\.(com|cn|edu)',"alex@oldboyedu.cn")
<re.Match object; span=(0, 17), match='alex@oldboyedu.cn'>
  • re.compile()  与直接使用 fullmatch 相比,可提高效率。
>>> pattern = re.compile('\w+@\w+\.(com|cn|edu)')
>>> pattern.fullmatch('alex@oldboyedu.cn')
<re.Match object; span=(0, 17), match='alex@oldboyedu.cn'>

Flags标识符

  • re.I(re.IGNORECASE):忽略大小写(括号内是完整写法,下同)
  • M(MULTILINE):多行模式,改变 '^' 和 '$' 的行为
  • S(DOTALL):改变 '.' 的行为,make the '.' special character match any character at all, including a newline; without this flag, '.' will match any except a newline.
  • X(re.VERBOSE):可以给你的表达式写注释,使其可读,下面这两个意思一样。
>>> re.search('a','Alex',re.I) #忽略大小写
<re.Match object; span=(0, 1), match='A'>
>>> re.search('foo.$','foo1\nfoo2\n')
<re.Match object; span=(5, 9), match='foo2'>
>>> re.search('foo.$','foo1\nfoo2\n',re.M) #匹配一行的结尾
<re.Match object; span=(0, 4), match='foo1'>
>>> re.search('.','\n') #匹配换行符之外的所有字符
>>> re.search('.','\n',re.S) #匹配所有的字符
<re.Match object; span=(0, 1), match='\n'>
>>> re.search('.  #test','alex\n')
>>> re.search('.  #test','alex\n',re.X) #加进注释
<re.Match object; span=(0, 1), match='a'>