Python正则表达式re模块,一文看懂【收藏】

1.1 用正则表达式查找文本

  • \d 匹配任何一个 0-9的数字
  • \d{3} 匹配这个模式3次,3是个变量
  • \d{3,5} 匹配这个模式3次到5次,这个事贪心匹配模式,如果出现五次,那么他就匹配最长的哪一个.
  • \d{3,5}? 非贪心匹配模式,只匹配最短的那个,问号在花括号后边则代表是非贪心匹配
  • () 利用括号分组,第一个括号为第一组,以此类推,用group(1)形式返回分组内容
  • 问号位于分组 ()? 后边,则代表可选匹配,有则匹配,没有就掠过
  • 利用管道符 | 匹配多个分组,是或的关系,有第一个匹配第一个,没有则依次往后匹配
  • + 加号匹配一次或多次,意味着加号之前的分组至少得出现一次
  • * 星号匹配零次或多次,意味着星号前边的分组可以不存在,也可以出现多次,均可匹配。

案例:

  • 匹配这样一个电话号码:400-9946-555
    \d{3}-\d{4}-\d{3}
    

1.1.1 创建正则表达式对象

Python中所有表达式的函数都在 re 模块中。需导入模块!

  • import re 模块详解:

    Regex = re.compile(r'\d{3}-\d{4}-\d{3}')

    • re.compile() 传入一个正则表达式,即代表我们创建了一个表达式对象,简称:Regex对象,格式如上所示。

    mo = Regex.search('My number is 415-555-4242.')

    • search()在文本中查找该正则表达式的所有匹配,如果没有找到将返回 None, 找到了将返回一个Match对象

    mo.group()
    返回Match对象中实际匹配的文本。

案例:

phoneNumberRegex = re.compile(r'\d{3}-\d{3}-\d{4}')
mo = phoneNumberRegex.search('My number is 415-555-4242.')
print(str(mo.group()))

1.1.2 用括号为正则表达式分组

假定你想将029-33660111这样的座机电话号码区号单独提取出来,那么可以用括号为正则表达式分组:r'(\d{3})-(\d{7})'然后使用 group()匹配对象方法,从一个分组中获取匹配的文本,第一个括号为第一组,逐次增加,不传入参数或传入为0,则返回整个匹配。

案例:

如果想一次返回所有分组,则可以使用,groups() 方法, 返回的是一个元组。

import pyperclip, re

def RegexPhoneNumber(regex, num=0):
    """ 将400电话提取拷贝到剪贴板的程序 """
    # 接收剪贴板的文本
    text = pyperclip.paste()
    # 创建正则表达式对象
    textRegex = re.compile(regex)
    # 匹配该表达式中的文本
    mo = textRegex.search(text)
    if mo is not None: 
        if num == 0:
            text = pyperclip.copy(mo.group())
            print('这段文字里有匹配的电话:' + mo.group())
            num1, num2 = mo.groups()  # 元组的多重赋值
            print('这段文字里有匹配的电话:' + num1)
            print('这段文字里有匹配的电话:' + num2)
        else:
            # 您的正则表达式分组了,并且只提取指定组的内容
            text = pyperclip.copy(mo.group(num))
            print('这段文字里有匹配的电话:' + mo.group(num))
    else:
        print('这段文字里没有匹配的电话!')

RegexPhoneNumber(r'(\d{3})-(\d{4}-\d{3})')  # 匹配 400-9946-555 这种格式的正则

# RegexPhoneNumber(r'(\d{3})-(\d{4}-\d{3})', num=2)

1.1.3 利用管道匹配多个分组

字符|称为“管道”。匹配多个表达式中的一个,语法格式为:r'zhang|zhen',是或的关系,匹配这个或者那个。

案例:

>>> import re
>>> heroRegex = re.compile(r'zhang|zhen')
>>> mo1 = heroRegex.search('my name is zhang xing fu or zhang zhen?')
>>> mo1.group()
'zhang'
  • 如果前缀通用,那么可以将前缀移到括号外边,括号内用管道匹配,如果传入参数将匹配括号内第一次匹配的值

案例:

>>> batRegex = re.compile(r'Bat(man|mobile|copter|bat)')
>>> mo = batRegex.search('Batmobile lost a wheel')
>>> mo.group(1)
>>> mobile
>>> mo.group()
>>> Batmobile

1.1.4 利用问号实现可选匹配

有时我们会有这样的需求,例如想匹配的某个选项不是必须的,如果存在就匹配,不存在则略过,匹配其他的正则,此时可以使用 ()? 这样的方式。

案例1:

>>> import re
>>> batRegex = re.compile(r'Bat(wo)?man')
>>> mo1 = batRegex.search('the adventures of Batman')
>>> mo1.group()
'Batman'
>>> mo2 = batRegex.search('the adventures of Batwoman')
>>> mo2.group()
'Batwoman'

案例2:匹配一个电话号,有区号的则匹配没有区号则直接匹配电话,例如:029-33660111这样的格式。

>>> import re
>>> phoneNumber = re.compile(r'(\d{3}-)?\d{7}')
>>> mo1 = phoneNumber.search('我们公司的点化石:029-33660111')
>>> mo1.group()
'029-3366011'
>>> mo2 = phoneNumber.search('我们公司的点化石:33660111')
>>> mo2.group()
'3366011'

1.1.5 用星号匹配零次或多次

* 这个符号称为星号,匹配零次或多次,也就意味着星号前边的分组可以不存在,也可以出现多次,均可匹配。与之类似的是用 加号匹配一次或多次,意味着加号之前的分组至少得出现一次。

  • * 号匹配零次或多次

  • + 号匹配一次或多次

  • 案例:

    >>> batRegex = re.compile(r'Bat(wo)*man')
    >>> mo3 = batRegex.search('my name is Batman')
    >>> mo3.group()
    'Batman'
    >>> mo3 = batRegex.search('my name is Batwoman')
    >>> mo3.group()
    'Batwoman'
    >>> mo3 = batRegex.search('my name is Batwowowowowowoman')
    >>> mo3.group()
    'Batwowowowowowoman'
    
    # 加号匹配
    >>> sumRegex = re.compile(r'Bat(wo)+man')
    >>> mo = sumRegex.search('my name is Batwoman')
    >>> mo.group()
    'Batwoman'
    >>> mo = sumRegex.search('my name is Batwowowowowoman')
    >>> mo.group()
    'Batwowowowowoman'
    

1.2 findall()方法, 返回所有匹配:

  • 1、如果调用在一个没有分组的正则表达式上,例如\d\d\d-\d\d\d-\d\d\d\d,方法
    findall()将返回一个匹配字符串的列表,例如['415-555-9999', '212-555-0000']

  • 2、如果调用在一个有分组的正则表达式上,例如(\d\d\d)-(\d\d\d)-(\d\d\d\d),方法 findall()将返回一个字符串的元组的列表(每个分组对应一个字符串),例如[('415','555', '1122'), ('212', '555', '0000')]

  • 案例:

    >>> import re
    >>> phoneNumber = re.compile(r'\d{3}-\d{4}-\d{3}')
    >>> mo = phoneNumber.findall('公司的电话是:400-9946-555, 以前的是:400-6820-880')
    >>> mo
    ['400-9946-555', '400-6820-880']
    >>> phoneNumber = re.compile(r'(\d{3})-(\d{4})-(\d{3})')
    >>> mo = phoneNumber.findall('公司的电话是:400-9946-555, 以前的是:400-6820-880')
    >>> mo
    [('400', '9946', '555'), ('400', '6820', '880')]
    
    

1.3 字符分类

  • 常用字符分类的缩写代码:

    缩写字符分类 表示
    \d 0 到 9的任何数字
    \D 除 0 到 9 的数字以外的任何字符
    \w 任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
    \W 除字母、数字和下划线以外的任何字符
    \s 空格、制表符或换行符(可以认为是匹配“空白”字符)
    \S 除空格、制表符和换行符以外的任何字符

1.4 建立自己的字符分类

有时候你想匹配一组字符,但缩写的字符分类(\d、\w、\s 等)太宽泛。你可
以用方括号[]定义自己的字符分类。

  • 比较常用的几种方法总结

    常用写法 表示的意思
    [aeiouAEIOU] 匹配方括号内指定的字符
    [a-zA-Z0-9] 用短横线表示字母或数字的范围
    [.*?()] 方括号内普通的正则表达式符号不会被解释,他们匹配的就是本身自己
    [^aeiouAEIOU] 方括号内开始位置加上^这个符号,将代表不匹配方括号内指定的所有字符,返回除过指定字符以外的字符
  • 案例:

    import re
    # 匹配方括号内指定的字符
    >>> viowRegex = re.compile(r'[aeiouAEIOU]')
    >>> mo1 = viowRegex.findall('RoboCop eats baby food. BABY FOOD.')
    >>> mo1
    ['o', 'o', 'o', 'e', 'a', 'a', 'o', 'o', 'A', 'O', 'O']
    >>> viowRegex = re.compile(r'[^aeiouAEIOU]')
    >>> mo2 = viowRegex.findall('RoboCop eats baby food. BABY FOOD.')
    >>> mo2
    ['R', 'b', 'C', 'p', ' ', 't', 's', ' ', 'b', 'b', 'y', ' ', 'f', 'd', '.', ' ', 'B', 'B', 'Y', ' ', 'F', 'D', '.']
    

1.5 插入字符和美元字符

可以在正则表达式的开始处使用插入符号(^),表明匹配必须发生在被查找文本开始处。类似地,可以再正则表达式的末尾加上美元符号(,表明整个字符串必须匹配该模式,也就是说,只匹配该字符串的某个子集是不够的。

  • 比较常用的几种方法总结

    常用写法 表示的意思
    r'^Hello' 只匹配以'Hello'开始的字符串
    r'\d$' 只匹配以数字结尾的字符串
    r'^\w+\d+$' 只匹配以字母开头和数字结尾字符串
  • 案例:

    >>> Regex = re.compile(r'^Hello')
    >>> mo3 = Regex.search('Hello hai shi Hello')
    >>> mo3.group()
    'Hello'
    
    >>> mo3 = Regex.search(' hai shi Hello') == None
    >>> mo3
    True
    
    >>> Regex = re.compile(r'^\w+\d+$')
    >>> mo4 = Regex.search('zhangzhen456987')
    >>> mo4.group()
    'zhangzhen456987'
    

1.6 通配字符

在正则表达式中,.(句点)字符称为“通配符”。它匹配除了换行之外的所有字符。

  • 比较常用的几种方法总结

    常用写法 表示的意思
    r'.' 只匹配一个字符
    r'.*' 匹配所有字符,贪心模式,尽可能多的匹配
    r'.*? 非贪心匹配所有字符
    re.compile(r'.*', re.DOTALL) 匹配所有字符,包括换行字符
    re.compile(r'aoiue', re.I) 匹配字符,不论大小写都匹配

备注:如果想使用点-星匹配所有的字符包括换行,通过传入 re.DOTALL 作为 re.compile()的第二个参数,可以让句点字符匹配所有字符,包括换行字符。

1.7 正则表达式符号复习

  • ?匹配零次或一次前面的分组。
  • *匹配零次或多次前面的分组。
  • +匹配一次或多次前面的分组。
  • {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]匹配不在方括号内的任意字符。

你可能感兴趣的:(Python正则表达式re模块,一文看懂【收藏】)