添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

参考资料: Python3 re模块官方文档

什么是正则表达式

正则表达式又称规则表达式 ,许多编程语言都支持利用正则表达式进行字符串操作。Python中的 re 模块使 Python 语言拥有全部的正则表达式功能。

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个 规则字符串 ,这个 规则字符串 用来表达对字符串的一种过滤逻辑。正则表达式是一个特殊的字符组合,用来判断 字符串 是否与其匹配。

举个例子:

四条腿活得 —匹配— > 牛

以A开头的四个单词 —匹配—> “Andy”

正则表达式 —匹配— > 字符串

正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它 匹配 了。

本文主要介绍Python中re模块的常用 函数。

Python原始字符串

正则表达式使用反斜杠字符( '\' )来表示特殊形式或允许使用特殊字符而不调用其特殊意义。这与Python在字符串文字中的相同目的的使用相同。例如,要匹配文字反斜杠,可能必须将 '\\\\' 作为正则表达式字符串,因为正则表达式必须是 \\ ,每个反斜杠必须在普通的Python字符串文字中表示为 \\

解决方案是使用Python的原始字符串符号进行正则表达式模式,在以 'r' 为前缀的字符串文字中,反斜杠不以任何特殊的方式处理。所以 r'\n' 是一个包含 “\” “n” 的双字符串,而 “\n” 是包含换行符的单字符串。

正则表达式的构成

  • 普通字符(字符串和数字,例如:abc123)
  • 元字符(特殊字符,例如:. ^ $ * + ? { } | ( ) \)
  • 常用元字符表

    re.L ( re.LOCALE )

    影响 “w, “W, “b, 和 “B,这取决于当前的本地化设置。

    locales 是 C 语言库中的一项功能,是用来为需要考虑不同语言的编程提供帮助的。举个例子,如果你正在处理法文文本,你想用 “w+ 来匹配文字,但 “w 只匹配字符类 [A-Za-z];它并不能匹配 “é” 或 “ç”。如果你的系统配置适当且本地化设置为法语,那么内部的 C 函数将告诉程序 “é” 也应该被认为是一个字母。当在编译正则表达式时使用 LOCALE 标志会得到用这些 C 函数来处理 “w 後的编译对象;这会更慢,但也会象你希望的那样可以用 “w+ 来匹配法文文本。

    re.M ( re.MULTILINE )

    使用 “^” 只匹配字符串的开始,而 $ 则只匹配字符串的结尾和直接在换行(如果有的话)前的字符串结尾。当指定本标志后, “^” 匹配字符串的开始和字符串中每行的开始。同样的, $ 元字符匹配字符串结尾和字符串中每行的结尾(直接在每个换行之前)。

    re.S ( re.DOTALL )

    使 “.” 特殊字符完全匹配任何字符,包括换行;没有这个标志, “.” 匹配除了换行外的任何字符。

    re.X ( re.VERBOSE )

    该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。当该标志被指定时,在 RE 字符串中的空白符被忽略,除非该空白符在字符类中或在反斜杠后面;这可以让你更清晰地组织和缩进re表达式。它也可以允许你将注释写入re表达式,这些注释会被引擎忽略;注释用 “#“号 来标识,不过该符号不能在字符串或反斜杠后面。

    正则表达式实例:

    re.match() 尝试从字符串的起始位置匹配,如果起始位置不能匹配, re.match() 就返回None。

    re.match(pattern, string, flags=0)

  • pattern:匹配的正则表达式
  • string:要匹配的字符串
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等。
  • re.match 方法匹配成功后返回一个匹配对象,否则返回None。

    import re
    s = "life is short, you need Python."
    print(re.match(r'life', s))  # 从开始位置能成功匹配到
    print(re.match(r'Life', s, re.I))  # 使用re.I标志位来指定忽略大小写
    print(re.match(r'life', s).span())  # .span可以获取到具体匹配的起始位置
    print(re.match(r'Python', s))  # 从开始位置不能成功匹配到
    
    <_sre.SRE_Match object; span=(0, 4), match='life'>
    <_sre.SRE_Match object; span=(0, 4), match='life'>
    (0, 4)
    

    对于匹配对象可以使用group(num)和groups()来获取匹配表达式。

    group(num=0):匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。

    groups():返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

    import re
    s = "life is short, you need Python."
    ret = re.match(r'(.*) is (.*)', s)
    print("ret.group():", ret.group())
    print("ret.group(1, 2):", ret.group(1, 2))
    print("ret.group(1):", ret.group(1))
    print("ret.group(2):", ret.group(2))
    print("ret.groups():", ret.groups())
    
    ret.group(): life is short, you need Python.
    ret.group(1, 2): ('life', 'short, you need Python.')
    ret.group(1): life
    ret.group(2): short, you need Python.
    ret.groups(): ('life', 'short, you need Python.')
    

    分组命名匹配:

    (?P<分组的名字>正则规则) **注意:**是大写的P

    import re
    s = "life is short, you need Python."
    ret = re.match(r'(?P<m1>.*) is (?P<m2>.*)', s)
    print("ret.group():", ret.group())
    print("ret.group('m1'):", ret.group('m1'))  # 支持使用组名访问匹配项
    print("ret.group('m2'):", ret.group('m2'))
    print("ret.group(1, 2):", ret.group(1, 2))
    print("ret.group(1):", ret.group(1))
    print("ret.group(2):", ret.group(2))
    print("ret.groups():", ret.groups())
    
    ret.group(): life is short, you need Python.
    ret.group('m1'): life
    ret.group('m2'): short, you need Python.
    ret.group(1, 2): ('life', 'short, you need Python.')
    ret.group(1): life
    ret.group(2): short, you need Python.
    ret.groups(): ('life', 'short, you need Python.')
    

    re.search

    re.search 扫描整个字符串并返回第一个成功的匹配。

    re.search(pattern, string, flags=0)

  • pattern:匹配的正则表达式。
  • string:要匹配的字符串。
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
  • re.search()方法匹配成功后会返回一个匹配的对象,否则返回None。

    import re
    s = "life is short, you need Python."
    print(re.search(r'life', s))
    print(re.search(r'life', s).span())
    print(re.search(r'Python', s))
    print(re.search(r'Python', s).span())
    print(re.search(r'xxx', s))
    
    <_sre.SRE_Match object; span=(0, 4), match='life'>
    (0, 4)
    <_sre.SRE_Match object; span=(24, 30), match='Python'>
    (24, 30)
    

    同样可以使用group(num)groups() 来获取匹配表达式。

    import re
    s = "life is short, you need Python."
    ret = re.search(r'(.*) is (.*)', s)
    print(ret.group())
    print(ret.group(1, 2))
    print(ret.group(1))
    print(ret.group(2))
    print(ret.groups())
    
    life is short, you need Python.
    ('life', 'short, you need Python.')
    short, you need Python.
    ('life', 'short, you need Python.')
    

    re.match和re.search的区别:

    re.match只匹配字符串的开始,如果字符串的开始位置不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配,整个字符串都找不到匹配才返回None。

    re.split

    用匹配到的对象将字符串分割成列表并返回。

    re.split(pattern, string, maxsplit=0, flags=0)

  • pattern:匹配的正则表达式。
  • string:要匹配的字符串。
  • maxsplit:模式匹配后分割的最大次数,默认 0 表示分割所有的匹配。
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
  • import re
    s = "Abc123.aBc456.abC789"
    ret1 = re.split(r'\.', s)  # 用.分割字符串s
    ret2 = re.split(r'\.', s, 1)  # 用.分割字符串s,只分割一次
    ret3 = re.split(r'[.\d]+', s)  # 用.和数字分s
    print("用.分割字符串s:", ret1)
    print("用.分割字符串s,只分割一次:", ret2)
    print("用.和数字分s:", ret3)
    
    .分割字符串s: ['Abc123', 'aBc456', 'abC789']
    .分割字符串s只分割一次: ['Abc123', 'aBc456.abC789']
    .和数字分s: ['Abc', 'aBc', 'abC', '']
    

    当正则匹配项位于字符串的开头或结尾时,re.split()得到列表会有空元素。

    re.findall

    找到字符串中所有的匹配项,以列表的形式返回。

    re.findall(pattern, string, flags=0)

  • pattern:匹配的正则表达式。
  • string:要匹配的字符串。
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
  • import re
    s = "Abc123.aBc456.abC789"
    ret = re.findall(r'\d+', s)    # 找到所有的连续数字,并以列表形式返回
    print("所有的数字:", ret)
    
    所有的数字 ['123', '456', '789']
    

    re.sub

    re.sub用来替换字符串中的匹配项。

    re.sub(pattern, repl, string, count=0, flags=0)

  • pattern:匹配的正则表达式。
  • repl:替换的字符串,也可为一个函数。
  • string:要被查找替换的原始字符串。
  • count:模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
  • import re
    s = "life is short, you need Python.  # 人生苦短,我用Python。"
    # 删除#及后面的内容(把#及后面的字符替换成空字符串)
    s1 = re.sub(r'#.*$', "", s)
    print("去掉注释后:", s1)
    
    去掉注释后 life is short, you need Python.
    

    示例2(当repl参数是一个函数时):

    import re
    # 将匹配的数字乘于2
    def double(matched):
        num = int(matched.group("num"))  # 注意要转成int类型
        return str(num * 2)  # 将乘以2后的结果转成str类型
    s = "1 + 2 = 3"
    s1 = re.sub(r'(?P<num>\d+)', double, s)  # 分组命名匹配
    print("re.sub替换后:", s1)
    
    re.sub替换后 2 + 4 = 6
    

    re.compile

    将正则表达式模式编译为正则表达式对象,可用于使用其match()search()方法进行匹配,如下所述。

    re_obj = re.compile(pattern)
    ret = re_obj.match(string)
    
    ret = re.match(pattern, string)
    

    正则表达式练习

    匹配手机号

    ret = re.match(r'(1)[3578]\d{9}', s)
    
    ret = re.match(r'^([a-z.0-9]{1,26})@([a-z.0-9]{1,20})(.[a-z0-9]{1,8})$', s)
    
    ret = re.match(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$', s)