一、简介

  • 正则表达式本质上是一门语言,它不从属与Python!Python只是将他人写好的正则引擎集成到了语言内部,大多数编程语言都是这么干的
  • 正则表达式诞生的时间很长,应用非常广泛,是业界公认的字符串匹配工具。虽然有不同版本的内部引擎,但基本通用,也就是说,你在Python内写的正则表达式,可以移植到Linux的shell,Java语言等任何支持正则的场景中去
  • 正则表达式默认从左往右匹配
  • 正则表达式默认是贪婪模式
  • 正则表达式默认在匹配到了内容后,则终止匹配,不继续匹配
  • 对同一个问题,编写的正则表达式不是唯一的

二、语法

通用语法,和Python实现无关,核心:编写一个表达式字符串,用这个字符串匹配文本,所有字符均是英文状态下的字符

  1. 普通字符
    1. 字母、数字、汉子、下划线、以及没有特殊定义的符号,都是【普通字符】。正则表达式中的普通字符,在匹配的时候,只匹配与自身相同的一个字符
    2. 比如,表达式<font style="color:#F5222D;">c</font>,在匹配字符串<font style="color:#F5222D;">abcde</font>时,匹配结果是:成功;匹配到的内容是<font style="color:#F5222D;">c</font>;匹配到的位置开始于2,结束于3。
  2. 元字符
    1. 正则表达式中使用了很多元字符,用来表示一些特殊的含义或功能
表达式 匹配
<font style="color:#F5222D;">.</font> 小数点可以匹配除了换行符<font style="color:#F5222D;">\n</font>意外的任意一个字符
` ` 逻辑或操作符
<font style="color:#F5222D;">[]</font> 匹配字符集中的一个字符
<font style="color:#F5222D;">[^]</font> 对字符集求反,也就是上面的反操作,符号必须在方括号的最前面
<font style="color:#F5222D;">-</font> 定义<font style="color:#F5222D;">[]</font>里的一个字符区间,例如<font style="color:#F5222D;">[a-z]</font>
<font style="color:#F5222D;">\</font> 对紧跟其后的一个字符进行转义
<font style="color:#F5222D;">()</font> 对表达式进行分组,将圆括号内的内容当做一个整体,并获得匹配的值

例如:

  1. <font style="color:#F5222D;">a.c</font>匹配<font style="color:#F5222D;">abc</font>
  2. <font style="color:#F5222D;">(a|b)c</font>匹配<font style="color:#F5222D;">ac</font><font style="color:#F5222D;">bc</font>
  3. <font style="color:#F5222D;">[abc]1</font>匹配<font style="color:#F5222D;">a1</font>or<font style="color:#F5222D;">b1</font>or<font style="color:#F5222D;">c1</font>
  4. 使用方括号<font style="color:#F5222D;">[]</font>包含一系列字符,能够匹配其中任意一个字符。用<font style="color:#F5222D;">[^]</font>包含一系列字符,则能够匹配其中字符之外的任意一个字符
  5. <font style="color:#F5222D;">[ab5@]</font>匹配<font style="color:#F5222D;">a</font><font style="color:#F5222D;">b</font><font style="color:#F5222D;">5</font><font style="color:#F5222D;">@</font>
  6. <font style="color:#F5222D;">[^abc]</font>匹配<font style="color:#F5222D;">a</font>,<font style="color:#F5222D;">b</font>,<font style="color:#F5222D;">c</font>之外的任意一个字符
  7. <font style="color:#F5222D;">[f-k]</font>匹配<font style="color:#F5222D;">f~k</font> 之间的任意一个字母
  8. <font style="color:#F5222D;">[^A-F0-3]</font>匹配<font style="color:#F5222D;">A~F</font>以及<font style="color:#F5222D;">0~3</font>之外的任意一个字符

  1. 转义字符

一些无法书写或者具有特殊功能的字符,采用在前面加斜杠<font style="color:#F5222D;">'\'</font>

表达式 匹配
<font style="color:#F5222D;">\r,\n</font> 匹配回车和换行符
<font style="color:#F5222D;">\t</font> 匹配制表符
<font style="color:#F5222D;">\\</font> 匹配斜杠<font style="color:#F5222D;">\</font>
<font style="color:#F5222D;">\^</font> 匹配<font style="color:#F5222D;">^</font>符号
<font style="color:#F5222D;">\$</font> 匹配<font style="color:#F5222D;">$</font>符号
<font style="color:#F5222D;">\.</font> 匹配<font style="color:#F5222D;">.</font>符号

尚未列出的还有问号<font style="color:#9254DE;">?</font>、星号<font style="color:#9254DE;">*</font>和括号<font style="color:#9254DE;">()</font>等其他的符号。所有正则表达式中具有特殊含义的字符在匹配自身的时候,都要使用斜杠进行转义。这些转义字符的匹配方法与普通字符类似,也是匹配与之相同的一个字符。

例如表达式<font style="color:#F5222D;">\$d</font>,在匹配字符串<font style="color:#F5222D;">"abc$de"</font>时,匹配结果是:成功;匹配到的内容是<font style="color:#F5222D;">$d</font>;匹配到的位置开始于3,结束于5
  1. 预定义匹配字符集
正则表达式中的一些表示方法,可以同时匹配某个预定义字符集中的任意一个字符。比如,表达式<font style="color:#F5222D;">\d</font>可以匹配任意一个数字。虽然可以匹配其中任意字符,但是只能是一个,不是多个。如下表所示,注意大小写:
表达式 匹配
<font style="color:#F5222D;">\d</font> 任意一个数字,<font style="color:#F5222D;">0~9</font>中的任意一个
<font style="color:#F5222D;">\w</font> 任意一个字母或数字或下划线,也就是<font style="color:#F5222D;">A~Z</font>,<font style="color:#F5222D;">a~z</font>``,<font style="color:#F5222D;">0-9</font>中的任意一个
<font style="color:#F5222D;">\s</font> 空格、制表符、换页符等空白字符的其中任意一个
<font style="color:#F5222D;">\D</font> <font style="color:#F5222D;">\d</font>的反集,也就是非数字的任意一个字符,等同于<font style="color:#F5222D;">[^\d]</font>
<font style="color:#F5222D;">\W</font> <font style="color:#F5222D;">\w</font>的反集,等同于<font style="color:#F5222D;">[^\w]</font>
<font style="color:#F5222D;">\S</font> <font style="color:#F5222D;">\s</font>的反集,等同于<font style="color:#F5222D;">[^\s]</font>
例如表达式<font style="color:#F5222D;">\d\d</font>,在匹配<font style="color:#F5222D;">abc123</font>时,匹配的结果是:成功;匹配到的内容是12;匹配到的位置开始于3,结束于5
  1. 重复匹配
前面的表达式,无论是只能匹配一种字符的表达式,还是可以匹配多种字符其中任意一个的表达式,都只能匹配一次。但是有时候我们需要对某个片段进行重复匹配,例如手机号码13666666666,一般的新手可能会写成<font style="color:#F5222D;">\d\d\d\d\d\d\d\d\d\d\d</font>(注意,这不是一个恰当的表达式),不但写着费劲,看着也累,还不一定准确恰当 这种情况可以使用表达式再加上修饰匹配次数的特殊符号<font style="color:#F5222D;">{}</font>,不用重复书写表达式就可以重复匹配。比如<font style="color:#F5222D;">[abcd][abcd]</font>可以写成<font style="color:#F5222D;">[abcd]{2}</font> | 表达式 | 匹配 | | :—-: | —- | | <font style="color:#F5222D;">{n}</font> | 表达式重复n次,比如<font style="color:#F5222D;">\d{2}</font>相当于<font style="color:#F5222D;">\d\d</font>,<font style="color:#F5222D;">a{3}</font>相当于<font style="color:#F5222D;">aaa</font> | | <font style="color:#F5222D;">{m,n}</font> | 表达式至少重复<font style="color:#F5222D;">m</font>次,最多重复<font style="color:#F5222D;">n</font>次。比如<font style="color:#F5222D;">ab{1,3}</font>可以匹配<font style="color:#F5222D;">ab</font><font style="color:#F5222D;">abb</font><font style="color:#F5222D;">abbb</font> | | <font style="color:#F5222D;">{m,}</font> | 表达式至少重复m次,比如<font style="color:#F5222D;">\w\d{2,}</font>可以匹配<font style="color:#F5222D;">a12</font>,<font style="color:#F5222D;">_1111</font>,<font style="color:#F5222D;">M123</font>等等 | | <font style="color:#F5222D;">?</font> | 匹配表达式0次或者1次,相当于<font style="color:#F5222D;">{0,1}</font>,比如<font style="color:#F5222D;">a[cd]?</font>可以匹配<font style="color:#F5222D;">a,ac,ad</font> | | <font style="color:#F5222D;">+</font> | 表达式至少出现1次,相当于<font style="color:#F5222D;">{1,}</font>,比如<font style="color:#F5222D;">a+b</font>可以匹配<font style="color:#F5222D;">ab</font>,<font style="color:#F5222D;">aab</font>,<font style="color:#F5222D;">aaab</font>等等 | | <font style="color:#F5222D;">*</font> | 表达式出现0次到任意次,相当于<font style="color:#F5222D;">{0,}</font>,比如<font style="color:#F5222D;">\^*b</font>可以匹配<font style="color:#F5222D;">b</font>,<font style="color:#F5222D;">^^^b</font>等等 | 其中有些例子一定要注意!比如<font style="color:#F5222D;">ab{1,3}</font>中重复的是<font style="color:#F5222D;">b</font>而不是<font style="color:#F5222D;">ab</font><font style="color:#F5222D;">(ab){1,3}</font>这样重复的才是<font style="color:#F5222D;">ab</font>。表达式<font style="color:#F5222D;">\^*b</font>中重复的是<font style="color:#F5222D;">\^</font>而不是<font style="color:#F5222D;">^</font>,要从<font style="color:#F5222D;">左往右读</font>正则表达式,转义符号有更高的优先级,需要和后面的字符整体认读 表达式<font style="color:#F5222D;">\d+\.?\d*</font>在匹配<font style="color:#F5222D;">It costs $12.5</font>时,匹配的结果是:成功;匹配到的内容是12.5;匹配到的位置开始于10,结束于14 表达式<font style="color:#F5222D;">go{2,8}gle</font>在匹配<font style="color:#F5222D;">Ads by goooooogle</font>时,匹配的结果是:成功;匹配到的内容是goooooogle;匹配到的位置开始于7,结束于17
  1. 位置匹配
表达式 匹配
<font style="color:#F5222D;">^</font> 在字符串开始的地方匹配,符号本身不匹配任何字符
<font style="color:#F5222D;">$</font> 在字符串结束的地方匹配,符号本身不匹配任何字符
<font style="color:#F5222D;">\b</font> 匹配一个单词边界,也就是单词和空格之间的位置,符号本身不匹配任何字符
<font style="color:#F5222D;">\B</font> 匹配非单词边界,即左右两边都是<font style="color:#F5222D;">\w</font>范围或者左右两边都不是<font style="color:#F5222D;">\w</font>范围时的字符缝隙
表达式<font style="color:#F5222D;">^aaa</font>在匹配<font style="color:#F5222D;">xxx aaa xxx</font>时,匹配结果是:失败。因为<font style="color:#F5222D;">^</font>要求在字符串开始的地方匹配 表达式<font style="color:#F5222D;">aaa$</font>在匹配<font style="color:#F5222D;">xxx aaa xxx</font>时,匹配结果是:失败。因为<font style="color:#F5222D;">$</font>要求在字符串结束的地方匹配 表达式<font style="color:#F5222D;">.\b.</font>在匹配<font style="color:#F5222D;">@@@abc</font>时,匹配结果是:成功;匹配到的内容是<font style="color:#F5222D;">@a</font>;匹配到的位置开始于2,结束于4 表达式<font style="color:#F5222D;">\bend\b</font>在匹配<font style="color:#F5222D;">weekend,endfor,end</font>时,匹配结果是:成功;匹配到的内容是end;匹配到的位置开始于15,结束于18

三、re模块(三大搜索模块)

在Python中,通过内置的re模块提供对正则表达式的支持。正则表达式会被编译成一系列的字节码,然后由通过C编写的正则表达式引擎进行执行
表达式 匹配 返回值
<font style="color:#F5222D;">compile(pattern[, flags])</font> 根据包含正则表达式的字符串创建模式对象 re对象
<font style="color:#F5222D;">search(pattern, string[, flags])</font> 在字符串中查找 第一个匹配到的对象或者Non
<font style="color:#F5222D;">match(pattern, string[, flags])</font> 在字符串的开始处匹配模式 在字符串开头匹配到的对象或者None
<font style="color:#F5222D;">findall(pattern, string,flags)</font> 列出字符串中模式的所有匹配项 所有匹配到的字符串列表
  1. <font style="color:#F5222D;">compile(pattern[, flags])</font>
这个方法是re模块的工厂方法,用于将字符串形式的正则表达式编译为Pattern模式对象,可以实现更高效率的匹配。第二个参数flag是匹配模式。 使用<font style="color:#F5222D;">compile()</font>完成一次转换后,再次使用该匹配模式的时候就不用进行转换了。经过<font style="color:#F5222D;">compile()</font>转换的正则表达式对象也能使用普通的re方法。其用法如下
  1. import re
  2. pat = re.compile('abc123')
  3. print(pat.match('abc1234'))
  4. <re.Match object; span=(0, 6), match='abc123'>
  5. print(pat.match('abc1234').group())
  6. abc123
经过<font style="color:#F5222D;">compile()</font>方法编译过后的返回值是个re对象,它可以调用<font style="color:#F5222D;">match()</font><font style="color:#F5222D;">search()</font><font style="color:#F5222D;">findall()</font>等其他方法,但其他方法不能调用<font style="color:#F5222D;">compile()</font>方法。实际上,<font style="color:#F5222D;">match()</font><font style="color:#F5222D;">search()</font>等方法在使用前,Python内部帮你进行了compile的步骤 那么是使用compile()还是直接使用<font style="color:#F5222D;">re.match()</font>呢?看场景!如果你只是简单的匹配一下后就不用了,那么<font style="color:#F5222D;">re.match()</font>这种简便的调用方式无疑来得更简单快捷。如果你有个模式需要进行大量次数的匹配,那么先<font style="color:#F5222D;">compile</font>编译一下再匹配的方式,效率会高很多

以下都可直接通过re模块调用方法形式

  1. <font style="color:#F5222D;">match(pattern,string[,flags]</font><font style="color:#F759AB;">)</font>

<font style="color:#F5222D;">match()</font>方法会在给定字符串的<font style="color:#F5222D;">开头</font>进行匹配,如果匹配不成功则返回<font style="color:#F5222D;">None</font>,匹配成功返回一个匹配对象,这个对象有个<font style="color:#F5222D;">group()</font>方法,可以将匹配到的字符串给出

  1. ret = re.match(r'cherry','dherry123')
  2. print(ret)
  3. None
  4. ret = re.match(r'cherry','cherry123')
  5. print(ret)
  6. <re.Match object; span=(0, 6), match='cherry'>
  7. obj = re.match(r'cherry','cherry123')
  8. print(obj.group())
  9. cherry
对于一个<font style="color:#F5222D;"><_sre.SRE_Match object; span=(0, 3), match='abc'></font>对象,span指的是匹配到的字符在字符串中的位置下标,分别对应start和end。需要注意的是不包括end位置的下标,它是右开口的
  1. <font style="color:#F5222D;">search(pattern,string[,flags]</font>)
在文本内查找,返回第一个匹配到的字符串。它的返回值类型和使用方法与match()是一样的,唯一的区别就是查找的位置<font style="color:#F5222D;">不用固定在文本的开头</font> python ret = re.search(r'ry1','cherry123') print(ret) <re.Match object; span=(4, 7), match='ry1'> 4. <font style="color:#F5222D;">findall(pattern,string[,flags]</font>) 作为re模块的三大搜索函数之一,<font style="color:#F5222D;">findall()</font><font style="color:#F5222D;">match()</font><font style="color:#F5222D;">search()</font>的不同之处在于,前两者都是单值匹配,找到一个就忽略后面,直接返回不再查找了。而findall是全文查找,它的返回值是一个匹配到的字符串的列表。这个列表没有group()方法,没有start、end、span,更不是一个匹配对象,仅仅是个列表!如果一项都没有匹配到那么返回一个空列表
  1. obj = re.findall(r'ry1','cherry123ry1334ry1444')
  2. print(obj)
  3. ['ry1', 'ry1', 'ry1']