正则表达式并非Python独有的,它与语言无关。很多语言都支持正则表达式。

    我们经常用正则表达式来匹配电子邮件、手机号码、url等等。

    来看一个简单的正则表达式,用于匹配手机号码:

    表示匹配以1开头,第二位是3或5或7或8或9,后面9位是数字,且后面必须以9位数字结尾。满足该规则的手机号就说明匹配该正则了。

    Python里模块包含所有正则表达式的功能。

    注意:由于Python的字符串本身也用\转义,所以要特别注意:

    1. s = 'ABC\\'
    2. # 对应的正则表达式字符串变成:'ABC\'

    使用Python的r前缀,就不用考虑转义的问题了:

    1. s = r'ABC\'
    2. # 对应的正则表达式字符串不变:'ABC\'

    上面的正则用Python写则是:

    1. import re
    2. m = re.match(r'^1[35789]\d{9}$', '13271222223')
    3. print(m)
    4. print(m)

    输出:

    1. <_sre.SRE_Match object; span=(0, 11), match='13271222223'>
    2. None

    发现第二个例子匹配结果是None。Python中re模块match()方法判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None

    所以我们可以写如下判断代码:

    1. ok

    \d属于元字符。

    常用的元字符:

    重复

    {9}属于重复限定符。

    常用的限定符:

    [35789]表示匹配3或5或7或8或9中的某一个。像[aeiou]就匹配任何一个英文元音字母,匹配标点符号(.或?或!)。

    [0-9]代表的含意与\d就是完全一致的:一位数字;同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文的话)。

    使用正则切分字符串

    re模块里的split可以代替常规的split。示例:

    1. # coding: utf-8
    2. import re
    3. string = 'abc d e'
    4. print(string.split(' '))
    5. print(re.split(r'\s+', string))

    输出:

    1. ['abc', 'd', '', 'e']
    2. ['abc', 'd', 'e']

    我们发现常规的切分字符串无法识别连续的空格,但正则可以。

    正则表达式还可以提取子串。用()表示的就是要提取的分组。

    (\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,可以按顺序分析:\d{1,3}匹配1到3位的数字,(\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})

    1. import re
    2. print(m.group(0))
    3. print(m.group(1))
    4. print(m.groups())

    group(0)永远是原始字符串,group(1)group(2)……表示第1、2、……个子串。groups()返回所有子串的tuple。

    这里由于只有一个分组,所以打印group(2)会报错。

    贪婪匹配

    当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。

    比如我们要匹配数字102300后面的0

    1. import re
    2. m = re.match(r'^(\d+)(0*)$', '102300')
    3. print(m.groups())

    输出:

    1. ('102300', '')

    由于贪婪匹配,\d+会一直匹配到末尾,把整个数字都匹配了,0*就只能匹配空字符串了。我们改改:

    1. import re
    2. m = re.match(r'^(\d+?)(0*)$', '102300')
    3. print(m.groups())

    输出:

    1. ('1023', '00')

    加个?就可以让\d+采用非贪婪匹配。

    懒惰限定符:

    正则表达式非常强大,本节只是讲解了基础。更多关于正则的知识,大家可以找资料学习。