模式匹配与正则表达式

Python中所有的正则表达式的函数都在re模块中

  • re.compile()中传入一个字符串(原始字符串),表示正则表达式,将返回一个Regex模式对象

  • 使用search()方法查找传入的字符串,如果没有匹配到,返回None,匹配到的字符串将会被放在search()返回的Match对象的group()方法中

    1
    2
    3
    4
    5
    >>> import re
    >>> num=re.compile(r'\d\d\d\d-\d\d-\d\d')
    >>> birthday=num.search('birthday is 1926-28-17')
    >>> print("He's birthday is "+birthday.group())
    He's birthday is 1926-28-17
  • 如果想要从生日中提取年、月、日等信息的话,可以添加括号在正则表达式中创建分组。向group()中传入0或不传参数,返回匹配到的整个字符串;传入其余正整数$N$返回匹配到的第$N$部分

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> import re
    >>> num=re.compile(r'(\d\d\d\d)-(\d\d)-(\d\d)')
    >>> birthday=num.search('birthday is 1926-28-17')
    >>> birthday.group()
    '1926-28-17'
    >>> birthday.group(0)
    '1926-28-17'
    >>> birthday.group(1)
    '1926'
    >>> birthday.group(2)
    '28'
    >>> birthday.group(3)
    '17'
  • 如果想要一次性获得所有分组,使用groups()方法,返回值是元组类型

    1
    2
    3
    4
    5
    6
    >>> type(birthday.group())
    <class 'str'>
    >>> type(birthday.groups())
    <class 'tuple'>
    >>> birthday.groups()
    ('1926', '28', '17')
  • 如果待匹配的表达式有多个时,在表达式之间使用|(管道)可以达到目的。此时search返回的是第一次匹配到的字符串;如果想要获得所有的匹配,可以使用findall()来代替search(),但是findall()返回的是列表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> st=re.compile(r'orange|tangerine')
    >>> like=st.search('I like eat orange or tangerine.')
    >>> like.group()
    'orange'
    >>> like=st.findall('I like eat orange or tangerine.')
    >>> type(like)
    <class 'list'>
    >>> like
    ['orange', 'tangerine']
  • 利用(str)?可以实现可选匹配,在匹配的时候,str可以出现零次或一次

    1
    2
    3
    4
    5
    6
    7
    >>> num=re.compile(r'b(a)?b')
    >>> n=num.search('bab')
    >>> n1=num.search('bb')
    >>> n.group()
    'bab'
    >>> n1.group()
    'bb'
  • (str)*str部分可以出现零次或多次;(str)+ str部分可以出现一次或多次

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 星号匹配
    >>> num=re.compile(r'b(a)*b')
    >>> n=num.search('baaaaaaaaab')
    >>> n1=num.search('bb')
    >>> n.group()
    'baaaaaaaaab'
    >>> n1.group()
    'bb'
    // 加号匹配
    >>> num=re.compile(r'b(a)+b')
    >>> n=num.search('baaaaaaaaab')
    >>> n1=num.search('bab')
    >>> n.group()
    'baaaaaaaaab'
    >>> n1.group()
    'bab'
  • 利用花括号可以实现匹配特定的次数:(str){3,}将str匹配3次或更多次。(str){,5}将str匹配0-5次

    1
    2
    3
    4
    5
    6
    7
    >>> num=re.compile(r'(a){3}')
    >>> n=num.search('aaa')
    >>> n1=num.search('aa')
    >>> n.group()
    'aaa'
    >>> n1==None
    True
  • 正则表达式默认是“贪心”的,会尽可能匹配最长的字符串。在花括号后添加?可以改为非贪心匹配(匹配最短的)

    1
    2
    3
    4
    5
    6
    7
    8
    >>> num=re.compile(r'(a){3,5}')
    >>> n1=num.search('aaaaa')
    >>> n1.group()
    'aaaaa'
    >>> num=re.compile(r'(a){3,5}?')
    >>> n1=num.search('aaaaa')
    >>> n1.group()
    'aaa'
    缩写字符分类 表示
    \d 0到9的任何数字
    \D 除0到9的数字以外的任何字符
    \w 任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
    \W 除了字母、数字和下划线以外的任何字符
    \s 空格、制表符或换行符(可以认为是匹配“空白”字符)
    \S 除空格、制表符和换行符以外的任何字符
  • 可以使用[]来创建自己的字符分类。例如:[0-9]匹配所有的数字,[a-z]匹配所有的小写字母;在字符前加上^表示匹配不在创建字符分类中的所有字符。对于正则表达式符号,不需要进行转义

    1
    2
    3
    4
    5
    6
    7
    8
    >>> a=re.compile(r'[0-9]')
    >>> a1=re.compile(r'[^0-9]')
    >>> b=a.findall('abc123de')
    >>> b1=a1.findall('abc123de')
    >>> b
    ['1', '2', '3']
    >>> b1
    ['a', 'b', 'c', 'd', 'e']
  • 在正则表达式开始出插入^,表示匹配必须在被查找文本的开始出;在末尾插入$,表示必须以这个正则表达式的模式结束;同时使用二者,表示整个字符串必须匹配该模式
    r'^\d+$匹配全是数字的字符串

  • .可以匹配除了换行以外的所有字符,被称为“通配符”

    1
    2
    3
    4
    >>> a=re.compile(r'.234')
    >>> b=a.findall('1234 2234 3234')
    >>> b
    ['1234', '2234', '3234']
  • .*进行组合,可以匹配除\n以外的任意字符,任意长度的文本,默认是贪心的;.*?这种匹配是非贪心的。通过传入re.DOTALL作为第二个参数,可以实现匹配包括\n在内的所有字符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> num=re.compile(r'<.*>')
    >>> a=num.search('<1+2+3>*<4+5+6>+10')
    >>> a.group()
    '<1+2+3>*<4+5+6>'
    >>> num=re.compile(r'<.*?>')
    >>> a=num.search('<1+2+3>*<4+5+6>+10')
    >>> a.group()
    '<1+2+3>'
    >>> a=re.compile('.*',re.DOTALL)
    >>> a.search('123\n456\n').group()
    '123\n456\n'
  • re.compile()中传入re.IGNORECASEre.I作为第二个参数,可以让正则表达式匹配的时候忽略大小写

  • Regex对象的 sub()方法需要传入两个参数。第一个参数是一个字符串,用于取代发现的匹配。第二个参数是一个字符串,即正则表达式。sub()方法返回替换完成后的字符串。

    1
    2
    3
    >>> a=re.compile(r'I')
    >>> a.sub('You','I have an apple.')
    'You have an apple.'
  • 如果需要匹配复杂的文本模式,可能需要长的、费解的正则表达式。可以传入变量re.VERBOSE作为第二个参数

正则表达式符号的总结

  • ?匹配零次或一次前面的分组。
  • *匹配零次或多次前面的分组。
  • +匹配一次或多次前面的分组。
  • {n}匹配 n 次前面的分组。
  • {n,}匹配 n 次或更多前面的分组。
  • {,m}匹配零次到 m 次前面的分组。
  • {n,m}匹配至少 n 次、至多 m 次前面的分组。
  • {n,m}?或*?或+?对前面的分组进行非贪心匹配。
  • ^spam意味着字符串必须以 spam 开始。
  • spam$意味着字符串必须以 spam 结束。
  • .匹配所有字符,换行符除外。
  • \d\w\s 分别匹配数字、单词和空格。
  • \D\W\S 分别匹配出数字、单词和空格外的所有字符。
  • [abc]匹配方括号内的任意字符(诸如 a、b 或 c)。
  • [^abc]匹配不在方括号内的任意字符。

本文标题:模式匹配与正则表达式

文章作者:执念

发布时间:2019年02月11日 - 16:02

最后更新:2019年02月17日 - 19:02

原始链接:https://blog.wzy1999.wang/learn/pyl-5/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------
0%